Skip to content

Commit a039867

Browse files
committed
Create package vm
Package vm is low-level package for directly accessing virtual machine data, such as screen pixels, sprite-sheet, fonts or buttons state. This data can be manipulated by backend, console, utility functions, or a game itself. It is very useful for writing custom tools, new backends or even entire new API to be used by games. Code using vm package directly could be very fast, because it can use low-level Go functions such as copy. Please note though, that with great power comes great responsibility. You can easily shoot yourself in the foot if you are not careful enough how you change the data. For example, increasing the SpriteSheetWidth without adjusting the SpriteSheetData will likely result in a panic during sprite-drawing operations.
1 parent aad542c commit a039867

36 files changed

+951
-721
lines changed

controller.go

Lines changed: 16 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@
44
package pi
55

66
import (
7-
"github.com/hajimehoshi/ebiten/v2"
8-
97
"github.com/elgopher/pi/internal/input"
8+
"github.com/elgopher/pi/vm"
109
)
1110

1211
// Button is a virtual button on any game controller. The game controller can be a gamepad or a keyboard.
@@ -22,12 +21,12 @@ type Button int
2221
// First connected gamepad controller is player 0, second player 1 and so on.
2322
// On XBox controller [O] is A and Y, [X] is B and X.
2423
const (
25-
Left Button = 0
26-
Right Button = 1
27-
Up Button = 2
28-
Down Button = 3
29-
O Button = 4 // O is a first fire button
30-
X Button = 5 // X is a second fire button
24+
Left = vm.ControllerLeft
25+
Right = vm.ControllerRight
26+
Up = vm.ControllerUp
27+
Down = vm.ControllerDown
28+
O = vm.ControllerO // O is a first fire button
29+
X = vm.ControllerX // X is a second fire button
3130
)
3231

3332
// Btn returns true if a controller button is being pressed at this moment by player 0.
@@ -64,7 +63,7 @@ func BtnpPlayer(button Button, player int) bool {
6463
//
6564
// A bit of 1 means the button is pressed.
6665
func BtnBits() int {
67-
return controllers[0].bits(isPressed) + controllers[1].bits(isPressed)<<8
66+
return buttonBits(0, isPressed) + buttonBits(1, isPressed)<<8
6867
}
6968

7069
// BtnpBits returns the state of all controller buttons for players 0 and 1 as bitset.
@@ -76,10 +75,10 @@ func BtnBits() int {
7675
//
7776
// A bit of 1 means the button has just been pressed.
7877
func BtnpBits() int {
79-
return controllers[0].bits(input.IsPressedRepeatably) + controllers[1].bits(input.IsPressedRepeatably)<<8
78+
return buttonBits(0, input.IsPressedRepeatably) + buttonBits(1, input.IsPressedRepeatably)<<8
8079
}
8180

82-
func buttonDuration(player int, button Button) int {
81+
func buttonDuration(player int, button Button) uint {
8382
if button < Left || button > X {
8483
return 0
8584
}
@@ -88,130 +87,20 @@ func buttonDuration(player int, button Button) int {
8887
return 0
8988
}
9089

91-
return controllers[player].buttonDuration[button]
90+
return vm.Controllers[player].BtnDuration[button]
9291
}
9392

94-
func isPressed(duration int) bool {
93+
func isPressed(duration uint) bool {
9594
return duration > 0
9695
}
9796

98-
func updateController() {
99-
for player := 0; player < 8; player++ {
100-
controllers[player].update(player)
101-
}
102-
}
103-
104-
var controllers [8]controller
105-
106-
type controller struct {
107-
buttonDuration [6]int // left, right, up, down, o, x
108-
}
109-
110-
func (c *controller) update(player int) {
111-
c.updateDirections(player)
112-
c.updateFireButtons(player)
113-
}
114-
115-
func (c *controller) updateDirections(player int) {
116-
gamepadID := ebiten.GamepadID(player)
117-
118-
axisX := ebiten.StandardGamepadAxisValue(gamepadID, ebiten.StandardGamepadAxisLeftStickHorizontal)
119-
axisY := ebiten.StandardGamepadAxisValue(gamepadID, ebiten.StandardGamepadAxisLeftStickVertical)
120-
121-
if axisX < -0.5 ||
122-
ebiten.IsStandardGamepadButtonPressed(gamepadID, ebiten.StandardGamepadButtonLeftLeft) ||
123-
isKeyboardPressed(player, Left) {
124-
c.buttonDuration[Left] += 1
125-
c.buttonDuration[Right] = 0
126-
} else if axisX > 0.5 ||
127-
ebiten.IsStandardGamepadButtonPressed(gamepadID, ebiten.StandardGamepadButtonLeftRight) ||
128-
isKeyboardPressed(player, Right) {
129-
c.buttonDuration[Right] += 1
130-
c.buttonDuration[Left] = 0
131-
} else {
132-
c.buttonDuration[Right] = 0
133-
c.buttonDuration[Left] = 0
134-
}
135-
136-
if axisY < -0.5 ||
137-
ebiten.IsStandardGamepadButtonPressed(gamepadID, ebiten.StandardGamepadButtonLeftTop) ||
138-
isKeyboardPressed(player, Up) {
139-
c.buttonDuration[Up] += 1
140-
c.buttonDuration[Down] = 0
141-
} else if axisY > 0.5 ||
142-
ebiten.IsStandardGamepadButtonPressed(gamepadID, ebiten.StandardGamepadButtonLeftBottom) ||
143-
isKeyboardPressed(player, Down) {
144-
c.buttonDuration[Down] += 1
145-
c.buttonDuration[Up] = 0
146-
} else {
147-
c.buttonDuration[Up] = 0
148-
c.buttonDuration[Down] = 0
149-
}
150-
}
151-
152-
func (c *controller) updateFireButtons(player int) {
153-
gamepadID := ebiten.GamepadID(player)
154-
155-
if ebiten.IsStandardGamepadButtonPressed(gamepadID, ebiten.StandardGamepadButtonRightBottom) ||
156-
ebiten.IsStandardGamepadButtonPressed(gamepadID, ebiten.StandardGamepadButtonRightTop) ||
157-
isKeyboardPressed(player, O) {
158-
c.buttonDuration[O] += 1
159-
} else {
160-
c.buttonDuration[O] = 0
161-
}
162-
163-
if ebiten.IsStandardGamepadButtonPressed(gamepadID, ebiten.StandardGamepadButtonRightRight) ||
164-
ebiten.IsStandardGamepadButtonPressed(gamepadID, ebiten.StandardGamepadButtonRightLeft) ||
165-
isKeyboardPressed(player, X) {
166-
c.buttonDuration[X] += 1
167-
} else {
168-
c.buttonDuration[X] = 0
169-
}
170-
}
171-
172-
func (c *controller) bits(isSet func(int) bool) int {
97+
func buttonBits(player int, isSet func(uint) bool) int {
98+
c := vm.Controllers[player]
17399
var b int
174-
for i := 0; i <= int(X); i++ {
175-
if isSet(c.buttonDuration[i]) {
100+
for i := 0; i <= X; i++ {
101+
if isSet(c.BtnDuration[i]) {
176102
b += 1 << i
177103
}
178104
}
179105
return b
180106
}
181-
182-
// first array is player, then π key, then slice of Ebitengine keys.
183-
var keyboardMapping = [...][6][]ebiten.Key{
184-
// player0:
185-
{
186-
{ebiten.KeyLeft}, // left
187-
{ebiten.KeyRight}, // right
188-
{ebiten.KeyUp}, // up
189-
{ebiten.KeyDown}, // down
190-
{ebiten.KeyZ, ebiten.KeyC, ebiten.KeyN}, // o
191-
{ebiten.KeyX, ebiten.KeyV, ebiten.KeyM}, // x
192-
},
193-
// player1:
194-
{
195-
{ebiten.KeyS}, // left
196-
{ebiten.KeyF}, // right
197-
{ebiten.KeyE}, // up
198-
{ebiten.KeyD}, // down
199-
{ebiten.KeyShiftLeft}, // o
200-
{ebiten.KeyTab, ebiten.KeyW, ebiten.KeyQ, ebiten.KeyA}, // x
201-
},
202-
}
203-
204-
func isKeyboardPressed(player int, button Button) bool {
205-
if player >= len(keyboardMapping) {
206-
return false
207-
}
208-
209-
keys := keyboardMapping[player][button]
210-
for _, k := range keys {
211-
if ebiten.IsKeyPressed(k) {
212-
return true
213-
}
214-
}
215-
216-
return false
217-
}

defaults.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// (c) 2022 Jacek Olszak
2+
// This code is licensed under MIT license (see LICENSE for details)
3+
4+
package pi
5+
6+
import "github.com/elgopher/pi/vm"
7+
8+
const (
9+
defaultSpriteSheetWidth = 128
10+
defaultSpriteSheetHeight = 128
11+
defaultScreenWidth = 128
12+
defaultScreenHeight = 128
13+
)
14+
15+
var (
16+
//nolint:govet
17+
defaultPalette = [256]vm.RGB{
18+
{0, 0, 0}, // 0 - black
19+
{0x1D, 0x2B, 0x53}, // 1 - dark blue
20+
{0x7E, 0x25, 0x53}, // 2 - dark purple
21+
{0x00, 0x87, 0x51}, // 3 - dark green
22+
{0xAB, 0x52, 0x36}, // 4 - brown
23+
{0x5F, 0x57, 0x4F}, // 5 - dark gray
24+
{0xC2, 0xC3, 0xC7}, // 6 - light gray
25+
{0xff, 0xf1, 0xe8}, // 7 - white
26+
{0xFF, 0x00, 0x4D}, // 8 - red
27+
{0xFF, 0xA3, 0x00}, // 9 - orange
28+
{0xFF, 0xEC, 0x27}, // 10 - yellow
29+
{0x00, 0xE4, 0x36}, // 11 - green
30+
{0x29, 0xAD, 0xFF}, // 12 - blue
31+
{0x83, 0x76, 0x9C}, // 13 - indigo
32+
{0xFF, 0x77, 0xA8}, // 14 - pink
33+
{0xFF, 0xCC, 0xAA}, // 15 - peach
34+
}
35+
)

0 commit comments

Comments
 (0)