Sweeper
All checks were successful
Build Dusk / run-tests (push) Successful in 1m28s
Build Dusk / build-linux (push) Successful in 1m33s
Build Dusk / build-psp (push) Successful in 1m53s
Build Dusk / build-dolphin (push) Successful in 2m19s

This commit is contained in:
2026-02-10 21:06:09 -06:00
parent e1f08b07aa
commit b37e5f45ca
13 changed files with 374 additions and 32 deletions

View File

@@ -48,7 +48,12 @@ else
inputBind("q", INPUT_ACTION_CANCEL)
inputBind("escape", INPUT_ACTION_RAGEQUIT)
end
end
if INPUT_POINTER then
inputBind("mouse_x", INPUT_ACTION_POINTERX)
inputBind("mouse_y", INPUT_ACTION_POINTERY)
end
end
localeSet(DUSK_LOCALE_EN_US)

View File

@@ -5,4 +5,5 @@
add_asset(TILESET ui.png type=PALETTIZED tileWidth=8 tileHeight=8)
add_asset(TILESET cell.png type=PALETTIZED tileWidth=8 tileHeight=8)
add_asset(TILESET border.png type=PALETTIZED tileWidth=8 tileHeight=8)
add_asset(IMAGE grid_bg.png type=PALETTIZED)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 123 B

After

Width:  |  Height:  |  Size: 123 B

View File

@@ -8,6 +8,7 @@ module('glm')
module('text')
module('tileset')
module('texture')
module('input')
CELL_STATE_DEFAULT = 0
CELL_STATE_HOVER = 1
@@ -20,30 +21,46 @@ camera = cameraCreate(CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC)
tilesetUi = tilesetGetByName("ui")
textureUi = textureLoad(tilesetUi.texture)
tilesetBorder = tilesetGetByName("border")
textureBorder = textureLoad(tilesetBorder.texture)
textureGrid = textureLoad("minesweeper/grid_bg.dpi")
tilesetCell = tilesetGetByName("cell")
textureCell = textureLoad(tilesetCell.texture)
-- cellSliceDefault = tilesetPositionGetUV(tilesetCell, 3, 5)
cellSliceDefault = tilesetPositionGetUV(tilesetCell, 0, 4)
-- cellSliceHover = tilesetPositionGetUV(tilesetCell, 3, 4)
-- cellSliceDown = tilesetPositionGetUV(tilesetCell, 3, 6)
-- cellSliceDisabled = tilesetPositionGetUV(tilesetCell, 3, 7)
cellSliceDefault = tilesetPositionGetUV(tilesetCell, 3, 5)
cellSliceHover = tilesetPositionGetUV(tilesetCell, 3, 4)
cellSliceDown = tilesetPositionGetUV(tilesetCell, 3, 6)
cellSliceDisabled = tilesetPositionGetUV(tilesetCell, 3, 7)
width = 10
height = 14
sweepwerCols = 10
sweeperRows = 14
mouseX = -1
mouseY = -1
centerX = 0
centerY = 0
boardWidth = sweepwerCols * tilesetCell.tileWidth
boardHeight = sweeperRows * tilesetCell.tileHeight
i = 0
cells = {}
for y = 1, height do
for x = 1, width do
for y = 1, sweeperRows do
for x = 1, sweepwerCols do
cells[i] = CELL_STATE_DEFAULT
i = i + 1
end
end
function cellDraw(x, y, type)
slice = cellSliceDefault
local slice = cellSliceDefault
if type == CELL_STATE_HOVER then
slice = cellSliceHover
elseif type == CELL_STATE_DOWN then
slice = cellSliceDown
elseif type == CELL_STATE_DISABLED then
slice = cellSliceDisabled
end
spriteBatchPush(textureCell,
x, y,
@@ -55,7 +72,7 @@ function cellDraw(x, y, type)
end
function backgroundDraw()
local t = (TIME.time / 20) % 1
local t = (TIME.time / 40) % 1
local scaleX = screenGetWidth() / textureGrid.width
local scaleY = screenGetHeight() / textureGrid.height
local u0 = t * scaleX
@@ -72,6 +89,88 @@ function backgroundDraw()
)
end
function borderDraw(x, y, innerWidth, innerHeight)
-- Top Left
local uv = tilesetPositionGetUV(tilesetBorder, 0, 0)
spriteBatchPush(textureBorder,
x - tilesetBorder.tileWidth, y - tilesetBorder.tileWidth,
x, y,
colorWhite(),
uv.u0, uv.v0,
uv.u1, uv.v1
)
-- Top Right
uv = tilesetPositionGetUV(tilesetBorder, 10, 0)
spriteBatchPush(textureBorder,
x + innerWidth, y - tilesetBorder.tileHeight,
x + innerWidth + tilesetBorder.tileWidth, y,
colorWhite(),
uv.u0, uv.v0,
uv.u1, uv.v1
)
-- Bottom Left
uv = tilesetPositionGetUV(tilesetBorder, 0, 10)
spriteBatchPush(textureBorder,
x - tilesetBorder.tileWidth, y + innerHeight,
x, y + innerHeight + tilesetBorder.tileHeight,
colorWhite(),
uv.u0, uv.v0,
uv.u1, uv.v1
)
-- Bottom Right
uv = tilesetPositionGetUV(tilesetBorder, 10, 10)
spriteBatchPush(textureBorder,
x + innerWidth, y + innerHeight,
x + innerWidth + tilesetBorder.tileWidth, y + innerHeight + tilesetBorder.tileHeight,
colorWhite(),
uv.u0, uv.v0,
uv.u1, uv.v1
)
-- Top
uv = tilesetPositionGetUV(tilesetBorder, 1, 0)
spriteBatchPush(textureBorder,
x, y - tilesetBorder.tileHeight,
x + innerWidth, y,
colorWhite(),
uv.u0, uv.v0,
uv.u1, uv.v1
)
-- Bottom
uv = tilesetPositionGetUV(tilesetBorder, 1, 10)
spriteBatchPush(textureBorder,
x, y + innerHeight,
x + innerWidth, y + innerHeight + tilesetBorder.tileHeight,
colorWhite(),
uv.u0, uv.v0,
uv.u1, uv.v1
)
-- Left
uv = tilesetPositionGetUV(tilesetBorder, 0, 1)
spriteBatchPush(textureBorder,
x - tilesetBorder.tileWidth, y,
x, y + innerHeight,
colorWhite(),
uv.u0, uv.v0,
uv.u1, uv.v1
)
-- Right
uv = tilesetPositionGetUV(tilesetBorder, 10, 1)
spriteBatchPush(textureBorder,
x + innerWidth, y,
x + innerWidth + tilesetBorder.tileWidth, y + innerHeight,
colorWhite(),
uv.u0, uv.v0,
uv.u1, uv.v1
)
end
function sceneDispose()
end
@@ -79,26 +178,53 @@ function sceneUpdate()
end
function sceneRender()
-- UI
-- Update camera
cameraPushMatrix(camera)
camera.bottom = screenGetHeight()
camera.right = screenGetWidth()
cellDraw(0, 0, 0)
-- backgroundDraw()
-- Update mouse position
if INPUT_POINTER then
mouseX = inputGetValue(INPUT_ACTION_POINTERX) * screenGetWidth()
mouseY = inputGetValue(INPUT_ACTION_POINTERY) * screenGetHeight()
end
-- offsetX = 32
-- offsetY = 32
-- for y = 0, height - 1 do
-- for x = 0, width - 1 do
-- cellDraw(
-- x * tilesetCell.tileWidth + offsetX,
-- y * tilesetCell.tileHeight + offsetY,
-- cells[i]
-- )
-- end
-- end
centerX = math.floor(screenGetWidth() / 2)
centerY = math.floor(screenGetHeight() / 2)
-- Draw elements
backgroundDraw()
borderDraw(
centerX - (boardWidth / 2), centerY - (boardHeight / 2),
boardWidth, boardHeight
)
i = 0
-- Foreach cell
local offX = centerX - (boardWidth / 2)
local offY = centerY - (boardHeight / 2)
for y = 0, sweeperRows - 1 do
for x = 0, sweepwerCols - 1 do
i = y * sweepwerCols + x
-- Hovered
if
cells[i] == CELL_STATE_DEFAULT and
mouseX >= x * tilesetCell.tileWidth + offX and mouseX < (x + 1) * tilesetCell.tileWidth + offX and
mouseY >= y * tilesetCell.tileHeight + offY and mouseY < (y + 1) * tilesetCell.tileHeight + offY
then
cells[i] = CELL_STATE_HOVER
else
cells[i] = CELL_STATE_DEFAULT
end
cellDraw(
x * tilesetCell.tileWidth + offX,
y * tilesetCell.tileHeight + offY,
cells[i]
)
end
end
spriteBatchFlush()
cameraPopMatrix()

View File

@@ -146,6 +146,4 @@ void quadBuffer3D(
vertices[5].pos[0] = min[0];
vertices[5].pos[1] = max[1];
vertices[5].pos[2] = min[2];
printf("UVS: (%f, %f), (%f, %f)\n", uvMin[0], uvMin[1], uvMax[0], uvMax[1]);
}

View File

@@ -16,7 +16,7 @@ if(DUSK_TARGET_SYSTEM STREQUAL "linux")
PUBLIC
INPUT_SDL2=1
INPUT_KEYBOARD=1
INPUT_MOUSE=1
INPUT_POINTER=1
INPUT_GAMEPAD=1
)

View File

@@ -12,6 +12,7 @@
#include "util/math.h"
#include "time/time.h"
#include "debug/debug.h"
#include "display/display.h"
input_t INPUT;
@@ -51,9 +52,22 @@ void inputUpdate(void) {
if(INPUT.controller) break;
}
#endif
#if INPUT_KEYBOARD == 1
INPUT.keyboardState = SDL_GetKeyboardState(NULL);
#endif
#if INPUT_POINTER == 1
int pointerX, pointerY;
SDL_GetMouseState(&pointerX, &pointerY);
int windowWidth, windowHeight;
SDL_GetWindowSize(DISPLAY.window, &windowWidth, &windowHeight);
INPUT.mouseX = (float_t)pointerX / (float_t)windowWidth;
INPUT.mouseY = (float_t)pointerY / (float_t)windowHeight;
#endif
#elif DOLPHIN
PAD_ScanPads();

View File

@@ -5,4 +5,6 @@ LEFT,
RIGHT,
ACCEPT,
CANCEL,
RAGEQUIT
RAGEQUIT
POINTERX,
POINTERY,
1 id,
5 RIGHT,
6 ACCEPT,
7 CANCEL,
8 RAGEQUIT
9 POINTERX,
10 POINTERY,

View File

@@ -43,6 +43,12 @@ typedef struct {
const uint8_t *keyboardState;
#endif
#if INPUT_POINTER == 1
#if INPUT_SDL2 == 1
float_t mouseX, mouseY;
#endif
#endif
#elif DOLPHIN
int padState[INPUT_PAD_COUNT];
float_t pads[INPUT_PAD_COUNT][INPUT_GAMEPAD_AXIS_COUNT];

View File

@@ -31,9 +31,41 @@ inputbuttondata_t INPUT_BUTTON_DATA[] = {
{ .name = "lstick_up", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_LEFTX, .positive = false } } },
{ .name = "lstick_right", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_LEFTY, .positive = true } } },
{ .name = "lstick_left", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_LEFTY, .positive = false } } },
#else
{ .name = "a", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_A } },
{ .name = "b", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_B } },
{ .name = "x", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_X } },
{ .name = "y", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_Y } },
{ .name = "start", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_START } },
{ .name = "back", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_BACK } },
{ .name = "up", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_DPAD_UP } },
{ .name = "down", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_DPAD_DOWN } },
{ .name = "left", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_DPAD_LEFT } },
{ .name = "right", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_DPAD_RIGHT } },
{ .name = "l1", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_LEFTSHOULDER } },
{ .name = "r1", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_RIGHTSHOULDER } },
{ .name = "l3", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_LEFTSTICK } },
{ .name = "r3", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_RIGHTSTICK } },
{ .name = "lstick_down", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_LEFTY, .positive = true } } },
{ .name = "lstick_up", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_LEFTY, .positive = false } } },
{ .name = "lstick_right", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_LEFTX, .positive = true } } },
{ .name = "lstick_left", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_LEFTX, .positive = false } } },
{ .name = "rstick_down", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_RIGHTY, .positive = true } } },
{ .name = "rstick_up", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_RIGHTY, .positive = false } } },
{ .name = "rstick_right", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_RIGHTX, .positive = true } } },
{ .name = "rstick_left", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_RIGHTX, .positive = false } } },
{ .name = "l2", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_TRIGGERLEFT, .positive = true } } },
{ .name = "r2", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_TRIGGERRIGHT, .positive = true } } },
#endif
#endif
#if INPUT_POINTER == 1
{ .name = "mouse_x", { .type = INPUT_BUTTON_TYPE_POINTER, .pointerAxis = INPUT_POINTER_AXIS_X } },
{ .name = "mouse_y", { .type = INPUT_BUTTON_TYPE_POINTER, .pointerAxis = INPUT_POINTER_AXIS_Y } },
// { .name = "mouse_wheel_x", { .type = INPUT_BUTTON_TYPE_POINTER, .pointerAxis = INPUT_POINTER_AXIS_WHEEL_X } },
// { .name = "mouse_wheel_y", { .type = INPUT_BUTTON_TYPE_POINTER, .pointerAxis = INPUT_POINTER_AXIS_WHEEL_Y } },
#endif
#if INPUT_KEYBOARD == 1
{ .name = "a", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_A } },
{ .name = "b", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_B } },
@@ -229,6 +261,29 @@ float_t inputButtonGetValue(const inputbutton_t button) {
}
#endif
#if INPUT_POINTER == 1
case INPUT_BUTTON_TYPE_POINTER: {
switch(button.pointerAxis) {
case INPUT_POINTER_AXIS_X:
#if INPUT_SDL2 == 1
return INPUT.mouseX;
#endif
return 0.0f;
case INPUT_POINTER_AXIS_Y:
#if INPUT_SDL2 == 1
return INPUT.mouseY;
#endif
return 0.0f;
default: {
assertUnreachable("Unknown pointer axis");
return 0.0f;
}
}
}
#endif
#if INPUT_GAMEPAD == 1
case INPUT_BUTTON_TYPE_GAMEPAD: {
#if INPUT_SDL2 == 1

View File

@@ -28,6 +28,13 @@
#if INPUT_SDL2 == 1
typedef SDL_GameControllerButton inputgamepadbutton_t;
typedef SDL_GameControllerAxis inputgamepadaxis_t;
typedef enum {
INPUT_POINTER_AXIS_X,
INPUT_POINTER_AXIS_Y,
INPUT_POINTER_AXIS_Z,
INPUT_POINTER_AXIS_WHEEL_X,
INPUT_POINTER_AXIS_WHEEL_Y,
} inputpointeraxis_t;
#elif DOLPHIN == 1
typedef u16 inputgamepadbutton_t;
typedef enum {
@@ -49,6 +56,14 @@ typedef enum {
#if INPUT_KEYBOARD == 1
INPUT_BUTTON_TYPE_KEYBOARD,
#endif
#if INPUT_POINTER == 1
INPUT_BUTTON_TYPE_POINTER,
#endif
#if INPUT_TOUCH == 1
INPUT_BUTTON_TYPE_TOUCH,
#endif
#if INPUT_GAMEPAD == 1
INPUT_BUTTON_TYPE_GAMEPAD,
@@ -73,6 +88,10 @@ typedef struct {
#if INPUT_KEYBOARD == 1
inputscancode_t scancode;
#endif
#if INPUT_POINTER == 1
inputpointeraxis_t pointerAxis;
#endif
};
} inputbutton_t;

View File

@@ -28,6 +28,11 @@ void moduleInput(scriptcontext_t *context) {
#else
""
#endif
#if INPUT_POINTER == 1
"INPUT_POINTER = true\n"
#else
""
#endif
#if INPUT_SDL2 == 1
"INPUT_SDL2 = true\n"
#else
@@ -51,6 +56,10 @@ void moduleInput(scriptcontext_t *context) {
// Bind methods
lua_register(context->luaState, "inputBind", moduleInputBind);
lua_register(context->luaState, "inputIsDown", moduleInputIsDown);
lua_register(context->luaState, "inputPressed", moduleInputPressed);
lua_register(context->luaState, "inputReleased", moduleInputReleased);
lua_register(context->luaState, "inputGetValue", moduleInputGetValue);
}
int moduleInputIndex(lua_State *l) {
@@ -112,4 +121,79 @@ int moduleInputBind(lua_State *L) {
inputBind(btn, action);
return 0;
}
int moduleInputIsDown(lua_State *L) {
assertNotNull(L, "Lua state cannot be NULL");
if(!lua_isnumber(L, 1)) {
luaL_error(L, "inputIsDown: Expected action ID as first argument");
return 0;
}
const inputaction_t action = (inputaction_t)lua_tonumber(L, 1);
if(action < INPUT_ACTION_NULL || action >= INPUT_ACTION_COUNT) {
luaL_error(L, "inputIsDown: Invalid action ID %d", action);
return 0;
}
lua_pushboolean(L, inputIsDown(action));
return 1;
}
int moduleInputPressed(lua_State *L) {
assertNotNull(L, "Lua state cannot be NULL");
if(!lua_isnumber(L, 1)) {
luaL_error(L, "inputPressed: Expected action ID as first argument");
return 0;
}
const inputaction_t action = (inputaction_t)lua_tonumber(L, 1);
if(action < INPUT_ACTION_NULL || action >= INPUT_ACTION_COUNT) {
luaL_error(L, "inputPressed: Invalid action ID %d", action);
return 0;
}
lua_pushboolean(L, inputPressed(action));
return 1;
}
int moduleInputReleased(lua_State *L) {
assertNotNull(L, "Lua state cannot be NULL");
if(!lua_isnumber(L, 1)) {
luaL_error(L, "inputReleased: Expected action ID as first argument");
return 0;
}
const inputaction_t action = (inputaction_t)lua_tonumber(L, 1);
if(action < INPUT_ACTION_NULL || action >= INPUT_ACTION_COUNT) {
luaL_error(L, "inputReleased: Invalid action ID %d", action);
return 0;
}
lua_pushboolean(L, inputReleased(action));
return 1;
}
int moduleInputGetValue(lua_State *L) {
assertNotNull(L, "Lua state cannot be NULL");
if(!lua_isnumber(L, 1)) {
luaL_error(L, "inputGetValue: Expected action ID as first argument");
return 0;
}
const inputaction_t action = (inputaction_t)lua_tonumber(L, 1);
if(action < INPUT_ACTION_NULL || action >= INPUT_ACTION_COUNT) {
luaL_error(L, "inputGetValue: Invalid action ID %d", action);
return 0;
}
lua_pushnumber(L, inputGetCurrentValue(action));
return 1;
}

View File

@@ -28,4 +28,36 @@ int moduleInputIndex(lua_State *l);
* @param L The Lua state.
* @return Number of return values on the Lua stack.
*/
int moduleInputBind(lua_State *L);
int moduleInputBind(lua_State *L);
/**
* Script binding for checking if an input action is currently pressed.
*
* @param L The Lua state.
* @return Number of return values on the Lua stack.
*/
int moduleInputIsDown(lua_State *L);
/**
* Script binding for checking if an input action was pressed this frame.
*
* @param L The Lua state.
* @return Number of return values on the Lua stack.
*/
int moduleInputPressed(lua_State *L);
/**
* Script binding for checking if an input action was released this frame.
*
* @param L The Lua state.
* @return Number of return values on the Lua stack.
*/
int moduleInputReleased(lua_State *L);
/**
* Script binding for getting the value of an input axis.
*
* @param L The Lua state.
* @return Number of return values on the Lua stack.
*/
int moduleInputGetValue(lua_State *L);