Batman
5
.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
out
|
||||
cmake-**
|
||||
.idea
|
||||
.vs
|
||||
.vscode
|
||||
91
CmakeLists.txt
Normal file
@@ -0,0 +1,91 @@
|
||||
cmake_minimum_required(VERSION 3.24)
|
||||
project(KevEngine)
|
||||
|
||||
include(FetchContent)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
set(CMAKE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
set(DEFAULT_BUILD_TYPE "Release")
|
||||
if(EXISTS "${CMAKE_SOURCE_DIR}/.git")
|
||||
set(DEFAULT_BUILD_TYPE "Debug")
|
||||
endif()
|
||||
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
message(STATUS "Setting build type to '${DEFAULT_BUILD_TYPE}' as none was specified.")
|
||||
set(CMAKE_BUILD_TYPE "${DEFAULT_BUILD_TYPE}" CACHE STRING "Choose the type of build." FORCE)
|
||||
# Set the possible values of build type for cmake-gui
|
||||
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
|
||||
endif()
|
||||
|
||||
|
||||
if(WIN32) # Install dlls in the same directory as the executable on Windows
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
endif()
|
||||
|
||||
# Fetch LUA
|
||||
# ++++++++++
|
||||
FetchContent_Declare(
|
||||
lua
|
||||
URL https://github.com/marovira/lua/archive/refs/tags/5.4.4.tar.gz
|
||||
)
|
||||
FetchContent_MakeAvailable(lua)
|
||||
|
||||
# Fetch SOL2
|
||||
# ++++++++++
|
||||
FetchContent_Declare(
|
||||
sol2
|
||||
URL https://github.com/ThePhD/sol2/archive/refs/tags/v3.3.0.tar.gz
|
||||
)
|
||||
FetchContent_MakeAvailable(sol2)
|
||||
|
||||
set(USE_NGHTTP2 OFF)
|
||||
|
||||
FetchContent_Declare(cpr GIT_REPOSITORY https://github.com/libcpr/cpr.git
|
||||
GIT_TAG dec9422db3af470641f8b0d90e4b451c4daebf64) # Replace with your desired git commit from: https://github.com/libcpr/cpr/releases
|
||||
FetchContent_MakeAvailable(cpr)
|
||||
|
||||
|
||||
find_library(GDIPLUS_LIBRARY NAMES libgdiplus gdiplus)
|
||||
set(GDIPLUS_LIBRARY gdiplus)
|
||||
|
||||
set(LIBS XInput)
|
||||
|
||||
|
||||
set(SRC_FILES
|
||||
"src/AbstractGame.cpp"
|
||||
"src/Game.cpp"
|
||||
"src/GameDefines.h"
|
||||
"src/GameEngine.cpp"
|
||||
"src/GameWinMain.cpp"
|
||||
"src/resource.h")
|
||||
|
||||
add_executable(${PROJECT_NAME} WIN32 ${SRC_FILES})
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE cpr::cpr sol2 lua::lua ${LIBS})
|
||||
|
||||
|
||||
|
||||
# Copy /lua folder to output directory
|
||||
add_custom_target(CopyLuaScripts ALL
|
||||
COMMENT "Copying Lua scripts to output directory"
|
||||
)
|
||||
|
||||
add_custom_command(TARGET CopyLuaScripts POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua
|
||||
$<TARGET_FILE_DIR:${PROJECT_NAME}>/lua)
|
||||
|
||||
add_custom_target(CopyResources ALL
|
||||
COMMENT "Copying resources to output directory"
|
||||
)
|
||||
|
||||
add_custom_command(TARGET CopyResources POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/resources
|
||||
$<TARGET_FILE_DIR:${PROJECT_NAME}>/resources)
|
||||
|
||||
|
||||
133
lua/Flappy.lua
Normal file
@@ -0,0 +1,133 @@
|
||||
-- Flappy Bird Clone using GameEngine
|
||||
|
||||
local vector2 = require("vector2")
|
||||
local utils = require("utils")
|
||||
|
||||
-- Game Variables
|
||||
local bird = {
|
||||
position = vector2.new(100, 200),
|
||||
width = 30,
|
||||
height = 30,
|
||||
velocity = 0,
|
||||
jumpStrength = -8
|
||||
}
|
||||
|
||||
local gravity = 0.5
|
||||
local pipes = {}
|
||||
local pipeWidth = 60
|
||||
local pipeGap = 120
|
||||
local pipeSpeed = 2
|
||||
local score = 0
|
||||
local gameRunning = true
|
||||
local gameStarted = false
|
||||
local screenWidth = GameEngine:getWidth()
|
||||
local screenHeight = GameEngine:getHeight()
|
||||
|
||||
-- Function to spawn new pipes
|
||||
local function spawnPipe()
|
||||
--GameEngine:messageBox(tostring(screenHeight - pipeGap - 50))
|
||||
local pipeHeight = math.random(50, screenHeight - pipeGap - 50)
|
||||
--local pipeHeight =50
|
||||
table.insert(pipes, { x = screenWidth, y = pipeHeight })
|
||||
end
|
||||
|
||||
function setup_window()
|
||||
GameEngine:setTitle("BreakOut")
|
||||
GameEngine:setWidth(800)
|
||||
GameEngine:setHeight(600)
|
||||
GameEngine:setFrameRate(60)
|
||||
end
|
||||
|
||||
--- the set_keylist function
|
||||
--- @return string
|
||||
function set_keylist()
|
||||
return "R "
|
||||
end
|
||||
|
||||
--- the start function
|
||||
--- @return nil
|
||||
function start()
|
||||
screenWidth = GameEngine:getWidth()
|
||||
screenHeight = GameEngine:getHeight()
|
||||
|
||||
-- print(GameEngine:getRequest("https://dummyjson.com/c/3029-d29f-4014-9fb4"))
|
||||
end
|
||||
|
||||
-- Update game state
|
||||
function update()
|
||||
if not gameRunning then return end
|
||||
|
||||
-- Apply gravity
|
||||
bird.velocity = bird.velocity + gravity
|
||||
bird.position.y = bird.position.y + bird.velocity
|
||||
|
||||
-- Jumping mechanic
|
||||
if GameEngine:isKeyDown(" ") then
|
||||
bird.velocity = bird.jumpStrength
|
||||
end
|
||||
|
||||
-- Move pipes
|
||||
for i = #pipes, 1, -1 do
|
||||
pipes[i].x = pipes[i].x - pipeSpeed
|
||||
|
||||
-- Remove off-screen pipes
|
||||
if pipes[i].x + pipeWidth < 0 then
|
||||
table.remove(pipes, i)
|
||||
score = score + 1
|
||||
end
|
||||
end
|
||||
|
||||
-- Collision detection
|
||||
for _, pipe in ipairs(pipes) do
|
||||
if bird.position.x < pipe.x + pipeWidth and bird.position.x + bird.width > pipe.x then
|
||||
if bird.position.y < pipe.y or bird.position.y + bird.height > pipe.y + pipeGap then
|
||||
gameRunning = false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Check if bird hits ground or ceiling
|
||||
if bird.position.y + bird.height >= screenHeight or bird.position.y <= 0 then
|
||||
gameRunning = false
|
||||
end
|
||||
|
||||
-- Spawn pipes periodically
|
||||
if #pipes == 0 or pipes[#pipes].x < screenWidth - 200 then
|
||||
spawnPipe()
|
||||
end
|
||||
end
|
||||
|
||||
-- Draw game elements
|
||||
function draw()
|
||||
-- Clear screen
|
||||
GameEngine:fillScreen(Color.new(135, 206, 250)) -- Sky Blue background
|
||||
|
||||
-- Draw bird
|
||||
GameEngine:setColor(Color.new(255, 255, 0)) -- Yellow
|
||||
GameEngine:fillOval(bird.position.x, bird.position.y, bird.width, bird.height)
|
||||
|
||||
-- Draw pipes
|
||||
GameEngine:setColor(Color.new(0, 255, 0)) -- Green
|
||||
for _, pipe in ipairs(pipes) do
|
||||
GameEngine:fillRect(pipe.x, 0, pipeWidth, pipe.y)
|
||||
GameEngine:fillRect(pipe.x, pipe.y + pipeGap, pipeWidth, screenHeight - pipe.y - pipeGap)
|
||||
end
|
||||
|
||||
-- Draw score
|
||||
GameEngine:setColor(Color.new(255, 255, 255)) -- White
|
||||
GameEngine:drawText(tostring(score), 10, 10)
|
||||
|
||||
-- Game over message
|
||||
if not gameRunning then
|
||||
GameEngine:drawText("Game Over! Press R to restart", screenWidth / 2 - 80, screenHeight / 2)
|
||||
end
|
||||
end
|
||||
|
||||
-- Restart function
|
||||
function restart()
|
||||
bird.position.y = 200
|
||||
bird.velocity = 0
|
||||
pipes = {}
|
||||
score = 0
|
||||
gameRunning = true
|
||||
end
|
||||
182
lua/Pong.lua
Normal file
@@ -0,0 +1,182 @@
|
||||
-- annotation.lua contains EmmyLua annotations for cpp_function & cpp_variable
|
||||
package.path = package.path .. ";../?.lua"
|
||||
|
||||
local utils = require("utils")
|
||||
local vector2 = require("vector2")
|
||||
|
||||
local player = {
|
||||
position = vector2.new(0, 0),
|
||||
height = 100,
|
||||
speed = 5
|
||||
}
|
||||
|
||||
local ball = {
|
||||
x = 0,
|
||||
y = 0,
|
||||
size = 20,
|
||||
xspeed = 5,
|
||||
yspeed = 5,
|
||||
color = Color.new(0,255,255)
|
||||
}
|
||||
|
||||
local AI = {
|
||||
y = 200,
|
||||
height = 100,
|
||||
speed = 4
|
||||
}
|
||||
|
||||
local player_score = 0
|
||||
local ai_score = 0
|
||||
|
||||
local start_timer = 0
|
||||
local start_timer_max = 60
|
||||
local next_round = true
|
||||
|
||||
local countdown_text = 3
|
||||
|
||||
|
||||
|
||||
function update_player(player)
|
||||
if GameEngine:isKeyDown("W") then
|
||||
if (player.position.y >= 0) then
|
||||
player.position.y = player.position.y - player.speed
|
||||
end
|
||||
end
|
||||
|
||||
if GameEngine:isKeyDown("S") then
|
||||
if player.position.y + player.height < GameEngine:getHeight() then
|
||||
player.position.y = player.position.y + player.speed
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function update_ai()
|
||||
if ball.y < AI.y then
|
||||
if(AI.y > 0) then
|
||||
AI.y = AI.y - AI.speed
|
||||
end
|
||||
end
|
||||
|
||||
if ball.y > AI.y then
|
||||
if AI.y + AI.height < GameEngine:getHeight() then
|
||||
AI.y = AI.y + AI.speed
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function update_ball()
|
||||
ball.x = ball.x + ball.xspeed
|
||||
ball.y = ball.y + ball.yspeed
|
||||
|
||||
if utils.check_collision(ball.x, ball.y, ball.size, ball.size, player.position.x, player.position.y, 10, player.height) then
|
||||
ball.xspeed = -ball.xspeed * 1.1
|
||||
|
||||
end
|
||||
|
||||
if utils.check_collision(ball.x, ball.y, ball.size, ball.size, GameEngine:getWidth() - 10, AI.y, 10, AI.height) then
|
||||
ball.xspeed = -ball.xspeed * 1.1
|
||||
end
|
||||
|
||||
|
||||
if ball.x <= 0 then
|
||||
ai_score = ai_score + 1
|
||||
ball.x = math.floor(GameEngine:getWidth() / 2 - ball.size / 2)
|
||||
ball.y = math.floor(GameEngine:getHeight() / 2 - ball.size / 2)
|
||||
next_round = true
|
||||
start_timer = 0
|
||||
countdown_text = 3
|
||||
end
|
||||
|
||||
if ball.x >= GameEngine:getWidth() - ball.size then
|
||||
player_score = player_score + 1
|
||||
ball.x = math.floor(GameEngine:getWidth() / 2 - ball.size / 2)
|
||||
ball.y = math.floor(GameEngine:getHeight() / 2 - ball.size / 2)
|
||||
next_round = true
|
||||
start_timer = 0
|
||||
countdown_text = 3
|
||||
end
|
||||
|
||||
if ball.y <= 0 or ball.y >= GameEngine:getHeight() - ball.size then
|
||||
ball.yspeed = -ball.yspeed
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
function draw_player()
|
||||
GameEngine:setColor(Color.new(255,255,255))
|
||||
GameEngine:fillRect(0, math.floor(player.position.y), 10, player.height)
|
||||
end
|
||||
|
||||
function draw_ai()
|
||||
GameEngine:setColor(Color.new(255,255,0))
|
||||
GameEngine:fillRect(GameEngine:getWidth() - 10, AI.y, 10, AI.height)
|
||||
end
|
||||
|
||||
function draw_ball()
|
||||
GameEngine:setColor(ball.color)
|
||||
GameEngine:fillOval(ball.x, ball.y, ball.size, ball.size)
|
||||
end
|
||||
|
||||
--- the setup function
|
||||
--- @return nil
|
||||
function setup_window()
|
||||
GameEngine:setTitle("BreakOut")
|
||||
GameEngine:setWidth(800)
|
||||
GameEngine:setHeight(600)
|
||||
GameEngine:setFrameRate(60)
|
||||
end
|
||||
|
||||
--- the set_keylist function
|
||||
--- @return string
|
||||
function set_keylist()
|
||||
return "WASD"
|
||||
end
|
||||
|
||||
--- the start function
|
||||
--- @return nil
|
||||
function start()
|
||||
ball.x = GameEngine:getWidth() / 2 - ball.size / 2
|
||||
ball.y = GameEngine:getHeight() / 2 - ball.size / 2
|
||||
|
||||
end
|
||||
|
||||
--- the update function
|
||||
--- @param Engine GameEngine # The GameEngine instance.
|
||||
--- @return nil
|
||||
function update()
|
||||
if (start_timer < start_timer_max and next_round) then
|
||||
start_timer = start_timer + 1
|
||||
if start_timer % 20 == 0 then
|
||||
countdown_text = countdown_text - 1
|
||||
end
|
||||
return
|
||||
end
|
||||
if(next_round) then
|
||||
ball.xspeed = 5
|
||||
ball.yspeed = 5
|
||||
next_round = false
|
||||
end
|
||||
update_player(player)
|
||||
update_ball()
|
||||
update_ai()
|
||||
end
|
||||
|
||||
|
||||
--- the draw function
|
||||
--- @return nil
|
||||
function draw()
|
||||
GameEngine:fillScreen(Color.new(0, 0,0))
|
||||
-- draw the score
|
||||
GameEngine:setColor(Color.new(255,255,255))
|
||||
GameEngine:drawText(tostring(player_score), 10, 10)
|
||||
GameEngine:drawText(tostring(ai_score), GameEngine:getWidth() - 20, 10)
|
||||
if next_round then
|
||||
GameEngine:drawText(tostring(countdown_text), GameEngine:getWidth() / 2,GameEngine:getHeight() / 2 - 30)
|
||||
end
|
||||
draw_player()
|
||||
draw_ball()
|
||||
draw_ai()
|
||||
end
|
||||
236
lua/annotation.lua
Normal file
@@ -0,0 +1,236 @@
|
||||
---@meta
|
||||
--- This file provides type annotations for Lua scripts interacting with C++ via SOL2.
|
||||
|
||||
|
||||
--- The Color class exposed from C++
|
||||
--- @class Color
|
||||
--- @field r number # The red component of the color.
|
||||
--- @field g number # The green component of the color.
|
||||
--- @field b number # The blue component of the color.
|
||||
Color = {}
|
||||
|
||||
--- constructor
|
||||
--- @param r number # The red component of the color.
|
||||
--- @param g number # The green component of the color.
|
||||
--- @param b number # The blue component of the color.
|
||||
--- @return Color
|
||||
function Color.new(r, g, b) end
|
||||
|
||||
|
||||
--- The Bitmap class exposed from C++
|
||||
--- @class Bitmap
|
||||
--- @field filename string # The filename of the bitmap.
|
||||
Bitmap = {}
|
||||
|
||||
--- constructor
|
||||
--- @param filename string # The filename of the bitmap.
|
||||
--- @return Bitmap
|
||||
function Bitmap.new(filename) end
|
||||
|
||||
--- Sets the transparency color
|
||||
--- @param color Color # The color to set as transparent.
|
||||
--- @return nil
|
||||
function Bitmap:SetTransparencyColor(color) end
|
||||
|
||||
--- Sets the Opacity
|
||||
--- @param opacity number # The opacity to set.
|
||||
--- @return nil
|
||||
function Bitmap:SetOpacity(opacity) end
|
||||
|
||||
--- Gets if the bitmap exists
|
||||
--- @return boolean # True if the bitmap exists, false otherwise.
|
||||
function Bitmap:Exists() end
|
||||
|
||||
--- Gets the width of the bitmap
|
||||
--- @return number # The width of the bitmap.
|
||||
function Bitmap:GetWidth() end
|
||||
|
||||
--- Gets the height of the bitmap
|
||||
--- @return number # The height of the bitmap.
|
||||
function Bitmap:GetHeight() end
|
||||
|
||||
|
||||
--- The Textbox class exposed from C++
|
||||
--- @class Textbox
|
||||
--- @field text string # The text of the textbox.
|
||||
Textbox = {}
|
||||
|
||||
--- constructor
|
||||
--- @param text string # The text of the textbox.
|
||||
--- @return Textbox
|
||||
function Textbox.new(text) end
|
||||
|
||||
--- Set the bounds of the textbox
|
||||
--- @param x number # The x coordinate of the textbox.
|
||||
--- @param y number # The y coordinate of the textbox.
|
||||
--- @param width number # The width of the textbox.
|
||||
--- @param height number # The height of the textbox.
|
||||
--- @return nil
|
||||
function Textbox:SetBounds(x, y, width, height) end
|
||||
|
||||
--- Set the text of the textbox
|
||||
--- @param text string # The text of the textbox.
|
||||
--- @return nil
|
||||
function Textbox:SetText(text) end
|
||||
|
||||
--- Sets the background color of the textbox
|
||||
--- @param color Color # The color to set as the background.
|
||||
--- @return nil
|
||||
function Textbox:SetBackgroundColor(color) end
|
||||
|
||||
--- Sets the foreground color of the textbox
|
||||
--- @param color Color # The color to set as the foreground.
|
||||
--- @return nil
|
||||
function Textbox:SetForegroundColor(color) end
|
||||
|
||||
--- Sets the textbox to be enabled
|
||||
--- @param enabled boolean # True if the textbox is enabled, false otherwise.
|
||||
--- @return nil
|
||||
function Textbox:SetEnabled(enabled) end
|
||||
|
||||
--- Shows the textbox
|
||||
--- @return nil
|
||||
function Textbox:Show() end
|
||||
|
||||
--- Hides the textbox
|
||||
--- @return nil
|
||||
function Textbox:Hide() end
|
||||
|
||||
--- Gets the text in the textbox
|
||||
--- @return string # The text in the textbox.
|
||||
function Textbox:GetText() end
|
||||
|
||||
|
||||
|
||||
--- The Game engine class exposed from C++
|
||||
--- @class Engine
|
||||
GameEngine = {}
|
||||
|
||||
--- @type
|
||||
GameEngine = GameEngine
|
||||
|
||||
|
||||
---Sets the title of the window.
|
||||
---@param title string # The new title.
|
||||
---@return nil
|
||||
function GameEngine:setTitle(title) end
|
||||
|
||||
--- Sets the width of the window.
|
||||
--- @param width number # The new width.
|
||||
--- @return nil
|
||||
function GameEngine:setWidth(width) end
|
||||
|
||||
--- Gets the window width.
|
||||
--- @return number # The width of the window.
|
||||
function GameEngine:getWidth() end
|
||||
|
||||
--- Gets the window height.
|
||||
--- @return number # The height of the window.
|
||||
function GameEngine:getHeight() end
|
||||
|
||||
--- Sets the height of the window.
|
||||
--- @param height number # The new height.
|
||||
--- @return nil
|
||||
function GameEngine:setHeight(height) end
|
||||
|
||||
--- Sets the frame rate of the window.
|
||||
--- @param frameRate number # The new frame rate.
|
||||
--- @return nil
|
||||
function GameEngine:setFrameRate(frameRate) end
|
||||
|
||||
--- Sets the drawing color
|
||||
--- @param color Color # The new color.
|
||||
--- @return nil
|
||||
function GameEngine:setColor(color) end
|
||||
|
||||
--- Fills the screen
|
||||
--- @param color Color # The color to fill the screen with.
|
||||
--- @return nil
|
||||
function GameEngine:fillScreen(color) end
|
||||
|
||||
--- message box
|
||||
--- @param message string # The message to display.
|
||||
--- @return nil
|
||||
function GameEngine:messageBox(message) end
|
||||
|
||||
|
||||
--- Draw a bitmap
|
||||
--- @param bitmap Bitmap # The bitmap to draw.
|
||||
--- @param x number # The x coordinate of the bitmap.
|
||||
--- @param y number # The y coordinate of the bitmap.
|
||||
function GameEngine:drawBitmap(bitmap, x, y) end
|
||||
|
||||
--- Draws a rectangle
|
||||
--- @param x number # The x coordinate of the rectangle.
|
||||
--- @param y number # The y coordinate of the rectangle.
|
||||
--- @param width number # The width of the rectangle.
|
||||
--- @param height number # The height of the rectangle.
|
||||
--- @return nil
|
||||
function GameEngine:drawRect(x, y, width, height) end
|
||||
|
||||
|
||||
--- fills a rectangle
|
||||
--- @param x number # The x coordinate of the rectangle.
|
||||
--- @param y number # The y coordinate of the rectangle.
|
||||
--- @param width number # The width of the rectangle.
|
||||
--- @param height number # The height of the rectangle.
|
||||
--- @return nil
|
||||
function GameEngine:fillRect(x, y, width, height) end
|
||||
|
||||
--- draws an oval
|
||||
--- @param x number # The x coordinate of the oval.
|
||||
--- @param y number # The y coordinate of the oval.
|
||||
--- @param width number # The width of the oval.
|
||||
--- @param height number # The height of the oval.
|
||||
function GameEngine:drawOval(x, y, width, height) end
|
||||
|
||||
--- fills an oval
|
||||
--- @param x number # The x coordinate of the oval.
|
||||
--- @param y number # The y coordinate of the oval.
|
||||
--- @param width number # The width of the oval.
|
||||
--- @param height number # The height of the oval.
|
||||
function GameEngine:fillOval(x, y, width, height) end
|
||||
|
||||
--- draws text
|
||||
--- @param text string # The text to draw.
|
||||
--- @param x number # The x coordinate of the text.
|
||||
--- @param y number # The y coordinate of the text.
|
||||
--- @return nil
|
||||
function GameEngine:drawText(text, x, y,) end
|
||||
|
||||
--- Checks if a key is pressed
|
||||
--- @param key string # The key to check.
|
||||
--- @return boolean # True if the key is pressed, false otherwise.
|
||||
function GameEngine:isKeyDown(key) end
|
||||
|
||||
|
||||
--- Gets the mouse Position X
|
||||
--- @return number # The x coordinate of the mouse.
|
||||
function GameEngine:getMouseX() end
|
||||
|
||||
|
||||
--- Gets the mouse Position Y
|
||||
--- @return number # The y coordinate of the mouse.
|
||||
function GameEngine:getMouseY() end
|
||||
|
||||
--- Get if the left mouse button isKeyDown
|
||||
--- @return boolean # True if the left mouse button is pressed, false otherwise.
|
||||
function GameEngine:isMouseLeftDown() end;
|
||||
|
||||
--- Get if the right mouse button isKeyDown
|
||||
--- @return boolean # True if the right mouse button is pressed, false otherwise.
|
||||
function GameEngine:isMouseRightDown() end;
|
||||
|
||||
--- Preform a Get Request
|
||||
--- @param url string # The url to get.
|
||||
--- @return string # The response from the server.
|
||||
function GameEngine:getRequest(url) end
|
||||
|
||||
--- Preform a Post Request
|
||||
--- @param url string # The url to post.
|
||||
--- @param data string # The data to post.
|
||||
function GameEngine:postRequest(url, data) end
|
||||
|
||||
--- Opens a dialog to enter a string
|
||||
--- @return string # The string entered by the user.
|
||||
function GameEngine:GetString() end
|
||||
68
lua/button.lua
Normal file
@@ -0,0 +1,68 @@
|
||||
local Button = {}
|
||||
Button.__index = Button
|
||||
|
||||
--- Constructor
|
||||
--- @param x number
|
||||
--- @param y number
|
||||
--- @param width number
|
||||
--- @param height number
|
||||
--- @param text string
|
||||
--- @param color Color
|
||||
--- @param callback function | nil
|
||||
--- @return Button
|
||||
function Button.new(x, y, width, height, text, color, callback)
|
||||
local self = setmetatable({}, Button)
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.width = width
|
||||
self.height = height
|
||||
self.text = text
|
||||
self.color = color
|
||||
self.callback = callback or function() end
|
||||
self.clicked = false
|
||||
return self
|
||||
end
|
||||
|
||||
--- Update function
|
||||
--- @param engine Engine
|
||||
function Button:update(engine)
|
||||
local mouseX = engine:getMouseX()
|
||||
local mouseY = engine:getMouseY()
|
||||
local isHovered = mouseX >= self.x and mouseX <= (self.x + self.width) and
|
||||
mouseY >= self.y and mouseY <= (self.y + self.height)
|
||||
|
||||
if isHovered and engine:isMouseLeftDown() then
|
||||
if not self.clicked then
|
||||
self.callback()
|
||||
self.clicked = true
|
||||
end
|
||||
else
|
||||
self.clicked = false
|
||||
end
|
||||
end
|
||||
|
||||
--- Draw function
|
||||
--- @param engine Engine
|
||||
function Button:draw(engine)
|
||||
local mouseX = engine:getMouseX()
|
||||
local mouseY = engine:getMouseY()
|
||||
local isHovered = mouseX >= self.x and mouseX <= (self.x + self.width) and
|
||||
mouseY >= self.y and mouseY <= (self.y + self.height)
|
||||
|
||||
local drawColor = isHovered and Color.new(self.color.r + 50, self.color.g + 50, self.color.b + 50) or self.color
|
||||
|
||||
engine:setColor(drawColor)
|
||||
engine:fillRect(self.x, self.y, self.width, self.height)
|
||||
|
||||
engine:setColor(Color.new(0, 0, 0)) -- Black text
|
||||
|
||||
local charWidth = 8
|
||||
local textWidth = #self.text * charWidth
|
||||
local textX = self.x + (self.width - textWidth) / 2
|
||||
local textY = self.y + (self.height - 8) / 2
|
||||
|
||||
engine:drawText(self.text, textX, textY)
|
||||
|
||||
end
|
||||
|
||||
return Button
|
||||
82
lua/script copy.lua
Normal file
@@ -0,0 +1,82 @@
|
||||
-- annotation.lua contains EmmyLua annotations for cpp_function & cpp_variable\
|
||||
|
||||
function create_button(x, y, width, height, text)
|
||||
return {
|
||||
x = x,
|
||||
y = y,
|
||||
width = width,
|
||||
height = height,
|
||||
text = text,
|
||||
hovered = false,
|
||||
was_pressed = false,
|
||||
onpressed = function() end
|
||||
}
|
||||
end
|
||||
|
||||
function draw_button(button)
|
||||
if button.hovered then
|
||||
Engine:setColor(Color.new(0, 255, 0))
|
||||
else
|
||||
Engine:setColor(Color.new(255, 0, 0))
|
||||
end
|
||||
Engine:fillRect(button.x, button.y, button.width, button.height)
|
||||
Engine:setColor(Color.new(0, 0, 0))
|
||||
Engine:drawText(button.text, button.x + 10, button.y + 10)
|
||||
end
|
||||
|
||||
function is_mouse_in_button(button, x, y)
|
||||
return x >= button.x and x <= button.x + button.width and y >= button.y and y <= button.y + button.height
|
||||
end
|
||||
|
||||
testButton = create_button(100, 100, 100, 50, "Test Button")
|
||||
|
||||
function update_button(button)
|
||||
if is_mouse_in_button(button, Engine:getMouseX(), Engine:getMouseY()) then
|
||||
button.hovered = true
|
||||
if Engine:isMouseLeftDown() and not button.was_pressed then
|
||||
button.onpressed()
|
||||
button.was_pressed = true
|
||||
elseif not Engine:isMouseLeftDown() then
|
||||
button.was_pressed = false
|
||||
end
|
||||
else
|
||||
button.hovered = false
|
||||
button.was_pressed = false
|
||||
end
|
||||
end
|
||||
|
||||
--- the setup function
|
||||
--- @return nil
|
||||
function setup_window()
|
||||
Engine:setTitle("Hello World new")
|
||||
Engine:setWidth(800)
|
||||
Engine:setHeight(600)
|
||||
Engine:setFrameRate(60)
|
||||
|
||||
testButton.onpressed = function()
|
||||
Engine:messageBox("Button Pressed")
|
||||
end
|
||||
end
|
||||
|
||||
--- the set_keylist function
|
||||
--- @return string
|
||||
function set_keylist()
|
||||
return "WASD"
|
||||
end
|
||||
|
||||
--- the update function
|
||||
--- @param Engine GameEngine # The GameEngine instance.
|
||||
--- @return nil
|
||||
function update()
|
||||
update_button( testButton)
|
||||
end
|
||||
|
||||
|
||||
--- the draw function
|
||||
--- @return nil
|
||||
function draw()
|
||||
Engine:setColor(Color.new(0, 0, 0))
|
||||
Engine:fillScreen(Color.new(255, 255, 255))
|
||||
|
||||
draw_button(testButton)
|
||||
end
|
||||
501
lua/script.lua
Normal file
@@ -0,0 +1,501 @@
|
||||
-- Tetris Game using GameEngine
|
||||
|
||||
local vector2 = require("vector2")
|
||||
local button = require("button")
|
||||
|
||||
-- Constants
|
||||
local GRID_WIDTH = 10
|
||||
local GRID_HEIGHT = 19
|
||||
local BLOCK_SIZE = 30
|
||||
local FALL_SPEED = 0.5
|
||||
|
||||
local screenWidth = 800
|
||||
local screenHeight = 600
|
||||
|
||||
-- Tetromino shapes and colors
|
||||
local tetrominoes = {
|
||||
{ shape = {{1, 1, 1, 1}}, color = Color.new(0, 255, 255) }, -- I
|
||||
{ shape = {{1, 1}, {1, 1}}, color = Color.new(255, 255, 0) }, -- O
|
||||
{ shape = {{0, 1, 0}, {1, 1, 1}}, color = Color.new(128, 0, 128) }, -- T
|
||||
{ shape = {{1, 1, 0}, {0, 1, 1}}, color = Color.new(0, 255, 0) }, -- S
|
||||
{ shape = {{0, 1, 1}, {1, 1, 0}}, color = Color.new(255, 0, 0) }, -- Z
|
||||
{ shape = {{1, 1, 1}, {1, 0, 0}}, color = Color.new(255, 165, 0) }, -- L
|
||||
{ shape = {{1, 1, 1}, {0, 0, 1}}, color = Color.new(0, 0, 255) } -- J
|
||||
}
|
||||
|
||||
-- Game State
|
||||
local grid = {}
|
||||
local currentPiece = {}
|
||||
local pieceX, pieceY = 4, 0
|
||||
local fallTimer = 0
|
||||
local lastKeyState = { Left = false, Right = false, Down = false, Rotate = false, Space = true }
|
||||
|
||||
-- enum of gameState, Main Menu, Playing, Submitting Name, Game Over
|
||||
|
||||
local MAIN_MENU = 0
|
||||
local PLAYING = 1
|
||||
local GAME_OVER = 2
|
||||
local SUBMITTING_NAME = 3
|
||||
|
||||
local gameState = MAIN_MENU
|
||||
|
||||
local titleScreenBitmap
|
||||
|
||||
|
||||
local nameTextBox
|
||||
local score = 0
|
||||
|
||||
-- list of bitmap frames that should be animated
|
||||
local leaderboardFrames = {}
|
||||
|
||||
local leaderboardFrameTimer = 0
|
||||
local leaderboardFrameIndex = 1
|
||||
local leaderboardFreamSpeed = 1
|
||||
|
||||
|
||||
local yesButton = button.new(300, 400, 100, 50, "Yes", Color.new(0, 255, 0), function()
|
||||
print("Sending Post")
|
||||
local playerName = nameTextBox:GetText()
|
||||
|
||||
if playerName == "" then playerName = "Anonymous" end
|
||||
|
||||
local data = "{ \"player\": \"" .. playerName .. "\", \"score\": " .. score .. " }"
|
||||
local response = GameEngine:postRequest("https://api.brammie15.dev/leaderboard/tetris", data)
|
||||
if(response == "Error: Request timed out") then
|
||||
netError = true
|
||||
end
|
||||
print(response)
|
||||
gameState = GAME_OVER
|
||||
end)
|
||||
local noButton = button.new(300, 500, 100, 50, "No", Color.new(255, 0, 0), function() gameState = GAME_OVER end)
|
||||
|
||||
|
||||
local hasGottenLeaderBoard = false
|
||||
local leaderboard = {}
|
||||
|
||||
local netError = false
|
||||
|
||||
local nextPiece = {}
|
||||
|
||||
local pieceBag = {}
|
||||
|
||||
|
||||
--- region BagStuff
|
||||
local function shuffleBag()
|
||||
pieceBag = {}
|
||||
local indices = {1, 2, 3, 4, 5, 6, 7}
|
||||
for i = #indices, 2, -1 do
|
||||
local j = math.random(i)
|
||||
indices[i], indices[j] = indices[j], indices[i]
|
||||
end
|
||||
for _, index in ipairs(indices) do
|
||||
table.insert(pieceBag, tetrominoes[index])
|
||||
end
|
||||
end
|
||||
|
||||
local function getNextPiece()
|
||||
if #pieceBag == 0 then
|
||||
shuffleBag()
|
||||
end
|
||||
local pieceData = table.remove(pieceBag, 1)
|
||||
return { shape = pieceData.shape, color = pieceData.color }
|
||||
end
|
||||
|
||||
local function getRandomPiece()
|
||||
local pieceData = tetrominoes[math.random(#tetrominoes)]
|
||||
return { shape = pieceData.shape, color = pieceData.color }
|
||||
end
|
||||
|
||||
--- endregion
|
||||
|
||||
local function checkCollision(px, py, piece)
|
||||
for y = 1, #piece.shape do
|
||||
for x = 1, #piece.shape[y] do
|
||||
if piece.shape[y][x] == 1 then
|
||||
if px + x < 1 or px + x > GRID_WIDTH or py + y > GRID_HEIGHT or (grid[py + y] and grid[py + y][px + x].value ~= 0) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function newPiece()
|
||||
currentPiece = nextPiece or getNextPiece()
|
||||
nextPiece = getNextPiece()
|
||||
pieceX, pieceY = 4, 0
|
||||
|
||||
if checkCollision(pieceX, pieceY, currentPiece) then
|
||||
gameState = SUBMITTING_NAME
|
||||
end
|
||||
end
|
||||
|
||||
--- region GhostPieces
|
||||
local function getGhostPieceY()
|
||||
local ghostY = pieceY
|
||||
while not checkCollision(pieceX, ghostY + 1, currentPiece) do
|
||||
ghostY = ghostY + 1
|
||||
end
|
||||
return ghostY
|
||||
end
|
||||
|
||||
local function drawGhostPiece()
|
||||
local ghostY = getGhostPieceY()
|
||||
GameEngine:setColor(Color.new(200, 200, 200)) -- Semi-transparent gray
|
||||
|
||||
for y = 1, #currentPiece.shape do
|
||||
for x = 1, #currentPiece.shape[y] do
|
||||
if currentPiece.shape[y][x] == 1 then
|
||||
GameEngine:fillRect((pieceX + x) * BLOCK_SIZE, (ghostY + y) * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- endregion
|
||||
|
||||
local function drawNextPiece()
|
||||
GameEngine:setColor(Color.new(255, 255, 255))
|
||||
GameEngine:drawText("Next:", 650, 100)
|
||||
|
||||
if nextPiece then
|
||||
for y = 1, #nextPiece.shape do
|
||||
for x = 1, #nextPiece.shape[y] do
|
||||
if nextPiece.shape[y][x] == 1 then
|
||||
GameEngine:setColor(nextPiece.color)
|
||||
GameEngine:fillRect(650 + x * BLOCK_SIZE, 120 + y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function clearLines()
|
||||
local linesCleared = 0
|
||||
for y = GRID_HEIGHT, 1, -1 do
|
||||
local full = true
|
||||
for x = 1, GRID_WIDTH do
|
||||
if grid[y][x].value == 0 then
|
||||
full = false
|
||||
break
|
||||
end
|
||||
end
|
||||
if full then
|
||||
table.remove(grid, y)
|
||||
table.insert(grid, 1, {})
|
||||
for x = 1, GRID_WIDTH do
|
||||
grid[1][x] = { value = 0, color = Color.new(255, 255, 255) }
|
||||
end
|
||||
linesCleared = linesCleared + 1
|
||||
end
|
||||
end
|
||||
|
||||
-- Score calculation based on cleared lines
|
||||
local scoreTable = { 100, 300, 500, 800 }
|
||||
if linesCleared > 0 then
|
||||
score = score + scoreTable[linesCleared] or 0
|
||||
end
|
||||
end
|
||||
|
||||
local function freezePiece()
|
||||
for y = 1, #currentPiece.shape do
|
||||
for x = 1, #currentPiece.shape[y] do
|
||||
if currentPiece.shape[y][x] == 1 then
|
||||
grid[pieceY + y][pieceX + x] = { value = 1, color = currentPiece.color }
|
||||
end
|
||||
end
|
||||
end
|
||||
clearLines()
|
||||
newPiece()
|
||||
end
|
||||
|
||||
local function rotatePiece()
|
||||
local newShape = {}
|
||||
for x = 1, #currentPiece.shape[1] do
|
||||
newShape[x] = {}
|
||||
for y = 1, #currentPiece.shape do
|
||||
newShape[x][#currentPiece.shape - y + 1] = currentPiece.shape[y][x]
|
||||
end
|
||||
end
|
||||
if not checkCollision(pieceX, pieceY, { shape = newShape }) then
|
||||
currentPiece.shape = newShape
|
||||
end
|
||||
end
|
||||
|
||||
local function drawGrid()
|
||||
for y = 1, GRID_HEIGHT do
|
||||
for x = 1, GRID_WIDTH do
|
||||
if grid[y][x].value ~= 0 then
|
||||
GameEngine:setColor(grid[y][x].color)
|
||||
GameEngine:fillRect(x * BLOCK_SIZE, y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE)
|
||||
end
|
||||
GameEngine:setColor(Color.new(50, 50, 50))
|
||||
GameEngine:drawRect(x * BLOCK_SIZE, y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE)
|
||||
end
|
||||
end
|
||||
GameEngine:setColor(Color.new(255, 255, 255))
|
||||
GameEngine:drawRect(BLOCK_SIZE, BLOCK_SIZE, GRID_WIDTH * BLOCK_SIZE, GRID_HEIGHT * BLOCK_SIZE)
|
||||
end
|
||||
|
||||
local function drawPiece()
|
||||
GameEngine:setColor(currentPiece.color)
|
||||
for y = 1, #currentPiece.shape do
|
||||
for x = 1, #currentPiece.shape[y] do
|
||||
if currentPiece.shape[y][x] == 1 then
|
||||
GameEngine:fillRect((pieceX + x) * BLOCK_SIZE, (pieceY + y) * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function setup_window()
|
||||
GameEngine:setTitle("Tetris")
|
||||
GameEngine:setWidth(screenWidth)
|
||||
GameEngine:setHeight(screenHeight)
|
||||
GameEngine:setFrameRate(60)
|
||||
end
|
||||
|
||||
--- the set_keylist function
|
||||
--- @return string
|
||||
function set_keylist()
|
||||
return "WASD "
|
||||
end
|
||||
|
||||
function start()
|
||||
-- Initialize grid
|
||||
for y = 1, GRID_HEIGHT do
|
||||
grid[y] = {}
|
||||
for x = 1, GRID_WIDTH do
|
||||
grid[y][x] = { value = 0, color = Color.new(255, 255, 255) }
|
||||
end
|
||||
end
|
||||
|
||||
nextPiece = getRandomPiece()
|
||||
newPiece()
|
||||
|
||||
nameTextBox = Textbox.new("")
|
||||
nameTextBox:SetBounds(250, 200, 200, 25)
|
||||
nameTextBox:Hide()
|
||||
|
||||
titleScreenBitmap = Bitmap.new("resources/tetrisLogo.bmp", true)
|
||||
|
||||
|
||||
-- load frame0 - 4
|
||||
for i = 0, 4 do
|
||||
print("loading frame" .. i)
|
||||
local bmp = Bitmap.new("resources/leaderboard/frame" .. i .. ".bmp", true)
|
||||
bmp:SetTransparencyColor(Color.new(255, 0, 255))
|
||||
table.insert(leaderboardFrames, bmp)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function update()
|
||||
-- print(GameEngine:getMouseX(), GameEngine:getMouseY())
|
||||
if gameState == PLAYING then
|
||||
|
||||
fallTimer = fallTimer + 1 / 60
|
||||
if fallTimer >= FALL_SPEED then
|
||||
if not checkCollision(pieceX, pieceY + 1, currentPiece) then
|
||||
pieceY = pieceY + 1
|
||||
else
|
||||
freezePiece()
|
||||
end
|
||||
fallTimer = 0
|
||||
end
|
||||
|
||||
|
||||
local leftPressed = GameEngine:isKeyDown("A")
|
||||
local rightPressed = GameEngine:isKeyDown("D")
|
||||
local downPressed = GameEngine:isKeyDown("S")
|
||||
local rotatePressed = GameEngine:isKeyDown("W")
|
||||
local spacePressed = GameEngine:isKeyDown(" ")
|
||||
|
||||
if leftPressed and not lastKeyState.Left and not checkCollision(pieceX - 1, pieceY, currentPiece) then
|
||||
pieceX = pieceX - 1
|
||||
end
|
||||
if rightPressed and not lastKeyState.Right and not checkCollision(pieceX + 1, pieceY, currentPiece) then
|
||||
pieceX = pieceX + 1
|
||||
end
|
||||
if downPressed and not lastKeyState.Down and not checkCollision(pieceX, pieceY + 1, currentPiece) then
|
||||
pieceY = pieceY + 1
|
||||
end
|
||||
|
||||
if spacePressed and not lastKeyState.Space then
|
||||
while not checkCollision(pieceX, pieceY + 1, currentPiece) do
|
||||
pieceY = pieceY + 1
|
||||
end
|
||||
freezePiece()
|
||||
end
|
||||
|
||||
|
||||
if rotatePressed and not lastKeyState.Rotate then
|
||||
rotatePiece()
|
||||
end
|
||||
|
||||
|
||||
lastKeyState.Left = leftPressed
|
||||
lastKeyState.Right = rightPressed
|
||||
lastKeyState.Down = downPressed
|
||||
lastKeyState.Rotate = rotatePressed
|
||||
lastKeyState.Space = spacePressed
|
||||
end
|
||||
|
||||
if gameState == GAME_OVER then
|
||||
|
||||
--Update leaderboard gif
|
||||
leaderboardFrameTimer = leaderboardFrameTimer + 1 / 60
|
||||
if leaderboardFrameTimer >= leaderboardFreamSpeed then
|
||||
leaderboardFrameIndex = leaderboardFrameIndex + 1
|
||||
if leaderboardFrameIndex > #leaderboardFrames then
|
||||
leaderboardFrameIndex = 1
|
||||
end
|
||||
leaderboardFrameTimer = 0
|
||||
end
|
||||
|
||||
if GameEngine:isKeyDown("R") then
|
||||
gameState = PLAYING
|
||||
score = 0
|
||||
netError = false
|
||||
hasGottenLeaderBoard = false
|
||||
leaderboard = {}
|
||||
nameTextBox:SetText("")
|
||||
grid = {}
|
||||
for y = 1, GRID_HEIGHT do
|
||||
grid[y] = {}
|
||||
for x = 1, GRID_WIDTH do
|
||||
grid[y][x] = { value = 0, color = Color.new(255, 255, 255) }
|
||||
end
|
||||
end
|
||||
newPiece()
|
||||
end
|
||||
end
|
||||
|
||||
if gameState == SUBMITTING_NAME then
|
||||
yesButton:update(GameEngine)
|
||||
noButton:update(GameEngine)
|
||||
end
|
||||
|
||||
if gameState == MAIN_MENU then
|
||||
if GameEngine:isKeyDown(" ") then
|
||||
gameState = PLAYING
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function drawScoreBoard()
|
||||
GameEngine:fillScreen(Color.new(0, 0, 0))
|
||||
if not hasGottenLeaderBoard then
|
||||
|
||||
local response = GameEngine:getRequest("https://api.brammie15.dev/leaderboard/tetris")
|
||||
if response == "Error: Request timed out" then
|
||||
netError = true
|
||||
end
|
||||
|
||||
print(response)
|
||||
|
||||
-- format is
|
||||
-- NAME SCORE
|
||||
|
||||
if not netError then
|
||||
for line in response:gmatch("[^\r\n]+") do
|
||||
local name, score = line:match("([^%s]+)%s+(%d+)")
|
||||
table.insert(leaderboard, { name = name, score = score })
|
||||
end
|
||||
table.sort(leaderboard, function(a, b) return a.score > b.score end)
|
||||
end
|
||||
hasGottenLeaderBoard = true
|
||||
end
|
||||
|
||||
|
||||
|
||||
GameEngine:setColor(Color.new(255, 0, 0))
|
||||
GameEngine:drawText("Score: " .. score, 350, 250)
|
||||
|
||||
if hasGottenLeaderBoard then
|
||||
local NamesX = 600
|
||||
local ScoresX = 700
|
||||
local Y = 100
|
||||
|
||||
GameEngine:setColor(Color.new(255, 255, 0))
|
||||
-- GameEngine:drawText("Leaderboard", 600, 60)
|
||||
GameEngine:drawBitmap(leaderboardFrames[leaderboardFrameIndex], 450, 60)
|
||||
|
||||
if netError then
|
||||
GameEngine:setColor(Color.new(255, 0, 0))
|
||||
GameEngine:drawText("Error: Request timed out", 600, 100)
|
||||
GameEngine:drawText("Or server down", 600, 120)
|
||||
GameEngine:drawText("Not gonna check :p", 600, 140)
|
||||
return
|
||||
end
|
||||
|
||||
for i = 1, math.min(#leaderboard, 20) do
|
||||
GameEngine:setColor(Color.new(255, 255, 255))
|
||||
GameEngine:drawText(leaderboard[i].name, NamesX, Y)
|
||||
GameEngine:drawText(leaderboard[i].score, ScoresX, Y)
|
||||
Y = Y + 20
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function drawGame()
|
||||
GameEngine:fillScreen(Color.new(0, 0, 0))
|
||||
drawGrid()
|
||||
drawGhostPiece()
|
||||
drawPiece()
|
||||
drawNextPiece() -- Draw the next piece preview
|
||||
GameEngine:setColor(Color.new(255, 255, 255))
|
||||
GameEngine:drawText("Score: " .. score, 650, 50)
|
||||
end
|
||||
|
||||
function drawGameOver()
|
||||
nameTextBox:Hide()
|
||||
GameEngine:setColor(Color.new(255, 0, 0))
|
||||
GameEngine:fillScreen(Color.new(0, 0, 0))
|
||||
GameEngine:drawText("Game Over", 350, 300)
|
||||
GameEngine:drawText("Press R to restart", 350, 350)
|
||||
|
||||
drawScoreBoard()
|
||||
end
|
||||
|
||||
function drawSubmitName()
|
||||
GameEngine:fillScreen(Color.new(0, 0, 0))
|
||||
GameEngine:setColor(Color.new(255, 255, 255))
|
||||
GameEngine:drawText("Name:", 200, 200)
|
||||
local charwidth = 8
|
||||
local submitText = "Would you like to submit to the leaderboard"
|
||||
local submitTextWidth = #submitText * charwidth
|
||||
GameEngine:drawText(submitText, 400 - submitTextWidth / 2, 50)
|
||||
nameTextBox:Show()
|
||||
yesButton:draw(GameEngine)
|
||||
noButton:draw(GameEngine)
|
||||
|
||||
end
|
||||
|
||||
function drawMainMenu()
|
||||
GameEngine:drawBitmap(titleScreenBitmap, 0, 0)
|
||||
|
||||
--Press space to start
|
||||
GameEngine:setColor(Color.new(255, 255, 255))
|
||||
GameEngine:drawText("Press Space to Start", 350, 500)
|
||||
end
|
||||
|
||||
function draw()
|
||||
|
||||
if gameState == PLAYING then
|
||||
drawGame()
|
||||
end
|
||||
|
||||
if gameState == GAME_OVER then
|
||||
drawGameOver()
|
||||
end
|
||||
|
||||
if gameState == SUBMITTING_NAME then
|
||||
drawSubmitName()
|
||||
end
|
||||
|
||||
if gameState == MAIN_MENU then
|
||||
drawMainMenu()
|
||||
end
|
||||
end
|
||||
131
lua/script_old.lua
Normal file
@@ -0,0 +1,131 @@
|
||||
-- annotation.lua contains EmmyLua annotations for cpp_function & cpp_variable\
|
||||
|
||||
-- ball player
|
||||
|
||||
player = {
|
||||
x = 0,
|
||||
y = 0,
|
||||
size = 20
|
||||
}
|
||||
|
||||
|
||||
avoid_cubes = {}
|
||||
|
||||
timer = 0
|
||||
max_timer = 10
|
||||
|
||||
function create_cube(x, y, size, timer_to_explode, exploded, death_timer)
|
||||
return {
|
||||
x = x,
|
||||
y = y,
|
||||
size = size,
|
||||
timer_to_explode = timer_to_explode,
|
||||
death_timer = death_timer,
|
||||
exploded = exploded
|
||||
}
|
||||
end
|
||||
|
||||
function create_random_cube()
|
||||
local x = math.random(0, 800)
|
||||
local y = math.random(0, 600)
|
||||
local size = math.random(10, 50)
|
||||
local timer_to_explode = math.random(50, 200)
|
||||
local exploded = false
|
||||
local death_timer = math.random(50, 200)
|
||||
return create_cube(x, y, size, timer_to_explode, exploded, death_timer)
|
||||
end
|
||||
|
||||
|
||||
|
||||
--- @param Engine GameEngine
|
||||
--- @param cube table
|
||||
function draw_cube(Engine, cube)
|
||||
if cube.exploded then
|
||||
Engine:setColor(Color.new(255, 0, 0))
|
||||
Engine:fillRect(cube.x, cube.y, cube.size, cube.size)
|
||||
else
|
||||
Engine:setColor(Color.new(0, 255, 0))
|
||||
Engine:drawRect(cube.x, cube.y, cube.size, cube.size)
|
||||
end
|
||||
end
|
||||
|
||||
function update_cubes()
|
||||
for i, cube in ipairs(avoid_cubes) do
|
||||
cube.timer_to_explode = cube.timer_to_explode - 1
|
||||
if cube.timer_to_explode < 0 then
|
||||
cube.exploded = true
|
||||
end
|
||||
|
||||
if cube.exploded then
|
||||
cube.death_timer = cube.death_timer - 1
|
||||
if cube.death_timer < 0 then
|
||||
table.remove(avoid_cubes, i)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function draw_player(Engine)
|
||||
Engine:setColor(Color.new(255, 0, 0))
|
||||
Engine:fillRect(player.x, player.y, player.size, player.size)
|
||||
end
|
||||
|
||||
--- the setup function
|
||||
--- @param Engine GameEngine # The GameEngine instance.
|
||||
--- @return nil
|
||||
function setup_window(Engine)
|
||||
Engine:setTitle("Hello World new")
|
||||
Engine:setWidth(800)
|
||||
Engine:setHeight(600)
|
||||
Engine:setFrameRate(60)
|
||||
end
|
||||
|
||||
--- the set_keylist function
|
||||
--- @return string
|
||||
function set_keylist()
|
||||
return "WASD"
|
||||
end
|
||||
|
||||
--- the update function
|
||||
--- @param Engine GameEngine # The GameEngine instance.
|
||||
--- @return nil
|
||||
function update(Engine)
|
||||
if Engine:isKeyDown("W") then
|
||||
player.y = player.y - 5
|
||||
end
|
||||
|
||||
if Engine:isKeyDown("A") then
|
||||
player.x = player.x - 5
|
||||
end
|
||||
|
||||
if Engine:isKeyDown("S") then
|
||||
player.y = player.y + 5
|
||||
end
|
||||
|
||||
if Engine:isKeyDown("D") then
|
||||
player.x = player.x + 5
|
||||
end
|
||||
|
||||
timer = timer + 1
|
||||
if timer > max_timer then
|
||||
table.insert(avoid_cubes, create_random_cube())
|
||||
timer = 0
|
||||
end
|
||||
|
||||
update_cubes()
|
||||
|
||||
player.x = Engine:getMouseX()
|
||||
player.y = Engine:getMouseY()
|
||||
end
|
||||
|
||||
|
||||
--- the draw function
|
||||
--- @param Engine GameEngine # The GameEngine instance.
|
||||
--- @return nil
|
||||
function draw(Engine)
|
||||
Engine:fillScreen(Color.new(0, 0, 0))
|
||||
draw_player(Engine)
|
||||
for i, cube in ipairs(avoid_cubes) do
|
||||
draw_cube(Engine, cube)
|
||||
end
|
||||
end
|
||||
21
lua/utils.lua
Normal file
@@ -0,0 +1,21 @@
|
||||
|
||||
utils = {}
|
||||
|
||||
|
||||
--- @param x1 number
|
||||
--- @param x2 number
|
||||
--- @param w1 number
|
||||
--- @param h1 number
|
||||
--- @param y1 number
|
||||
--- @param y2 number
|
||||
--- @param w2 number
|
||||
--- @param h2 number
|
||||
--- @return boolean
|
||||
function utils.check_collision(x1, y1, w1, h1, x2, y2, w2, h2)
|
||||
return x1 < x2 + w2 and
|
||||
x2 < x1 + w1 and
|
||||
y1 < y2 + h2 and
|
||||
y2 < y1 + h1
|
||||
end
|
||||
|
||||
return utils
|
||||
68
lua/vector2.lua
Normal file
@@ -0,0 +1,68 @@
|
||||
-- Define 'Vector2' class with shared methods and metamethods
|
||||
--- @class Vector2
|
||||
--- @field x number
|
||||
--- @field y number
|
||||
local Vector2 = {} -- Declare Vector2 as a local table first
|
||||
|
||||
|
||||
|
||||
--- Calculate the dot product of two vectors
|
||||
--- @param v0 Vector2
|
||||
--- @param v1 Vector2
|
||||
--- @return number
|
||||
Vector2.dot = function(v0, v1)
|
||||
return v0.x * v1.x + v0.y * v1.y
|
||||
end
|
||||
|
||||
--- Calculate the add of two vectors
|
||||
--- @param v0 Vector2
|
||||
--- @param v1 Vector2
|
||||
--- @return Vector2
|
||||
Vector2.__add = function(v0, v1)
|
||||
return Vector2.new(v0.x + v1.x, v0.y + v1.y)
|
||||
end
|
||||
|
||||
|
||||
--- Calculate the sub of two vectors
|
||||
--- @param v0 Vector2
|
||||
--- @param v1 Vector2
|
||||
--- @return Vector2
|
||||
Vector2.__sub = function(v0, v1)
|
||||
return Vector2.new(v0.x - v1.x, v0.y - v1.y)
|
||||
end
|
||||
|
||||
--- Calcuate the length of a vector2
|
||||
--- @param v Vector2
|
||||
--- @return number
|
||||
Vector2.__len = function(v)
|
||||
return math.sqrt(v.x * v.x + v.y * v.y)
|
||||
end
|
||||
|
||||
|
||||
--- Vector2 to string
|
||||
--- @param v Vector2
|
||||
--- @return string
|
||||
Vector2.__tostring = function(v)
|
||||
return string.format("Vector2(%g, %g)", v.x, v.y)
|
||||
end
|
||||
|
||||
Vector2.add = function(self, other_vec)
|
||||
self.x = self.x + other_vec.x
|
||||
self.y = self.y + other_vec.y
|
||||
return self
|
||||
end
|
||||
|
||||
Vector2.__index = Vector2 -- Enable shared methods via __index
|
||||
|
||||
--- Constructor
|
||||
--- @param x number
|
||||
--- @param y number
|
||||
--- @return Vector2
|
||||
function Vector2.new(x, y)
|
||||
return setmetatable(
|
||||
{x = x or 0, y = y or 0}, -- Initialize x and y with defaults
|
||||
Vector2 -- Assign metatable
|
||||
)
|
||||
end
|
||||
|
||||
return Vector2 -- Return the Vector2 table
|
||||
BIN
resources/aPoes.bmp
Normal file
|
After Width: | Height: | Size: 177 KiB |
BIN
resources/leaderboard/frame0.bmp
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
resources/leaderboard/frame0.png
Normal file
|
After Width: | Height: | Size: 6.8 KiB |
BIN
resources/leaderboard/frame1.bmp
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
resources/leaderboard/frame1.png
Normal file
|
After Width: | Height: | Size: 6.9 KiB |
BIN
resources/leaderboard/frame2.bmp
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
resources/leaderboard/frame2.png
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
BIN
resources/leaderboard/frame3.bmp
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
resources/leaderboard/frame3.png
Normal file
|
After Width: | Height: | Size: 6.2 KiB |
BIN
resources/leaderboard/frame4.bmp
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
resources/leaderboard/frame4.png
Normal file
|
After Width: | Height: | Size: 6.2 KiB |
BIN
resources/normal.png
Normal file
|
After Width: | Height: | Size: 14 MiB |
BIN
resources/tetrisLogo.bmp
Normal file
|
After Width: | Height: | Size: 1.4 MiB |
BIN
resources/tetrisLogo.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
24
src/AbstractGame.cpp
Normal file
@@ -0,0 +1,24 @@
|
||||
//-----------------------------------------------------------------
|
||||
// AbstractGame Object
|
||||
// C++ Source - AbstractGame.cpp - version v8_01
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// Include Files
|
||||
//-----------------------------------------------------------------
|
||||
#include "GameEngine.h"
|
||||
#include "AbstractGame.h"
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// AbstractGame Member Functions
|
||||
//-----------------------------------------------------------------
|
||||
void AbstractGame::Initialize()
|
||||
{
|
||||
// Set required values
|
||||
GAME_ENGINE->SetTitle(_T("Game Engine version 8_01"));
|
||||
|
||||
// Set optional values
|
||||
GAME_ENGINE->SetWidth(640);
|
||||
GAME_ENGINE->SetHeight(480);
|
||||
GAME_ENGINE->SetFrameRate(50);
|
||||
}
|
||||
46
src/AbstractGame.h
Normal file
@@ -0,0 +1,46 @@
|
||||
//-----------------------------------------------------------------
|
||||
// AbstractGame Object
|
||||
// C++ Header - AbstractGame.h - version v8_01
|
||||
//
|
||||
// AbstractGame is the abstract class which declares the functions that a
|
||||
// game class needs to implement to work with the game engine
|
||||
//-----------------------------------------------------------------
|
||||
#pragma once
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// Include Files
|
||||
//-----------------------------------------------------------------
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
#include <string>
|
||||
//-----------------------------------------------------------------
|
||||
// AbstractGame Class
|
||||
//-----------------------------------------------------------------
|
||||
class AbstractGame
|
||||
{
|
||||
public :
|
||||
// Constructor(s) and destructor
|
||||
AbstractGame() = default;
|
||||
virtual ~AbstractGame() = default;
|
||||
|
||||
// Disabling copy/move constructors and assignment operators
|
||||
AbstractGame(const AbstractGame& other) = delete;
|
||||
AbstractGame(AbstractGame&& other) noexcept = delete;
|
||||
AbstractGame& operator=(const AbstractGame& other) = delete;
|
||||
AbstractGame& operator=(AbstractGame&& other) noexcept = delete;
|
||||
|
||||
// Game functions
|
||||
virtual void Initialize (); // implemented in the .cpp file
|
||||
|
||||
virtual void Start () = 0; // pure virtual function
|
||||
virtual void End () = 0; // pure virtual function
|
||||
virtual void MouseButtonAction (bool isLeft, bool isDown, int x, int y, WPARAM wParam) = 0; // pure virtual function
|
||||
virtual void MouseWheelAction (int x, int y, int distance, WPARAM wParam) = 0; // pure virtual function
|
||||
virtual void MouseMove (int x, int y, WPARAM wParam) = 0; // pure virtual function
|
||||
virtual void CheckKeyboard () = 0; // pure virtual function
|
||||
virtual void KeyPressed (TCHAR key) = 0; // pure virtual function
|
||||
virtual void Paint (RECT rect) const = 0; // pure virtual function
|
||||
virtual void Tick () = 0; // pure virtual function
|
||||
virtual void InitialiseBindings () = 0; // pure virtual function
|
||||
};
|
||||
306
src/Game.cpp
Normal file
@@ -0,0 +1,306 @@
|
||||
//-----------------------------------------------------------------
|
||||
// Main Game File
|
||||
// C++ Source - Game.cpp - version v8_01
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// Include Files
|
||||
//-----------------------------------------------------------------
|
||||
#include "Game.h"
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// Game Member Functions
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
Game::Game(const std::string &fileName): m_fileName(fileName) {
|
||||
// nothing to create
|
||||
// cpr::Response r = cpr::Get(cpr::Url{"http://www.httpbin.org/get"});
|
||||
// std::cout << r.text << std::endl;
|
||||
// int result = MessageBox(hWnd, "Enter a string?", "Input Request", MB_OKCANCEL);
|
||||
// if (result == IDOK) {
|
||||
// User pressed OK
|
||||
// }
|
||||
}
|
||||
|
||||
Game::~Game() {
|
||||
// nothing to destroy
|
||||
}
|
||||
|
||||
void Game::Initialize() {
|
||||
// Code that needs to execute (once) at the start of the game, before the game window is created
|
||||
|
||||
//Check if the file exists using fs
|
||||
if (!std::filesystem::exists(m_fileName)) {
|
||||
GAME_ENGINE->MessageBox("File does not exist");
|
||||
return;
|
||||
}
|
||||
|
||||
try{
|
||||
const auto scriptResult = m_state.safe_script_file(m_fileName);
|
||||
if (!scriptResult.valid()) {
|
||||
//Handle Error
|
||||
const sol::error err = scriptResult;
|
||||
std::cerr << "Load Script Error: " << err.what();
|
||||
GAME_ENGINE->MessageBox(err.what());
|
||||
}
|
||||
} catch (const sol::error& e) {
|
||||
std::cerr << "Error loading script: " << e.what() << std::endl;
|
||||
GAME_ENGINE->MessageBox(e.what());
|
||||
}
|
||||
|
||||
|
||||
AbstractGame::Initialize();
|
||||
// GAME_ENGINE->SetTitle(_T("Game Engine version 8_01"));
|
||||
|
||||
this->FunctionCall("setup_window");
|
||||
|
||||
// Set the keys that the game needs to listen to
|
||||
//Get return value from Lua function
|
||||
auto keyList = this->FunctionCall<std::string>("set_keylist");
|
||||
GAME_ENGINE->SetKeyList(keyList);
|
||||
|
||||
// tstringstream buffer;
|
||||
// buffer << _T("W");
|
||||
// buffer << (char) VK_LEFT;
|
||||
// buffer << (char) VK_RIGHT;
|
||||
// GAME_ENGINE->SetKeyList(buffer.str());
|
||||
|
||||
}
|
||||
|
||||
void Game::Start() {
|
||||
// Insert code that needs to execute (once) at the start of the game, after the game window is created
|
||||
this->FunctionCall("start");
|
||||
}
|
||||
|
||||
void Game::End() {
|
||||
// Insert code that needs to execute when the game ends
|
||||
}
|
||||
|
||||
void Game::Paint(RECT rect) const {
|
||||
this->FunctionCall("draw");
|
||||
}
|
||||
|
||||
void Game::Tick() {
|
||||
this->FunctionCall("update");
|
||||
}
|
||||
|
||||
void Game::MouseButtonAction(bool isLeft, bool isDown, int x, int y, WPARAM wParam) {
|
||||
// Insert code for a mouse button action
|
||||
|
||||
/* Example:
|
||||
if (isLeft == true && isDown == true) // is it a left mouse click?
|
||||
{
|
||||
if ( x > 261 && x < 261 + 117 ) // check if click lies within x coordinates of choice
|
||||
{
|
||||
if ( y > 182 && y < 182 + 33 ) // check if click also lies within y coordinates of choice
|
||||
{
|
||||
GAME_ENGINE->MessageBox(_T("Clicked."));
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void Game::MouseWheelAction(int x, int y, int distance, WPARAM wParam) {
|
||||
// Insert code for a mouse wheel action
|
||||
}
|
||||
|
||||
void Game::MouseMove(int x, int y, WPARAM wParam) {
|
||||
// Insert code that needs to execute when the mouse pointer moves across the game window
|
||||
|
||||
/* Example:
|
||||
if ( x > 261 && x < 261 + 117 ) // check if mouse position is within x coordinates of choice
|
||||
{
|
||||
if ( y > 182 && y < 182 + 33 ) // check if mouse position also is within y coordinates of choice
|
||||
{
|
||||
GAME_ENGINE->MessageBox("Mouse move.");
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
void Game::CheckKeyboard() {
|
||||
// Here you can check if a key is pressed down
|
||||
// Is executed once per frame
|
||||
|
||||
// if (GAME_ENGINE->IsKeyDown(_T('W'))) {
|
||||
// GAME_ENGINE->MessageBox("W key pressed");
|
||||
// }
|
||||
/* Example:
|
||||
if (GAME_ENGINE->IsKeyDown(_T('L'))) yIcon += xSpeed;
|
||||
if (GAME_ENGINE->IsKeyDown(_T('M'))) xIcon += xSpeed;
|
||||
if (GAME_ENGINE->IsKeyDown(_T('O'))) yIcon -= ySpeed;
|
||||
*/
|
||||
}
|
||||
|
||||
void Game::KeyPressed(TCHAR key) {
|
||||
// DO NOT FORGET to use SetKeyList() !!
|
||||
|
||||
// Insert code that needs to execute when a key is pressed
|
||||
// The function is executed when the key is *released*
|
||||
// You need to specify the list of keys with the SetKeyList() function
|
||||
|
||||
|
||||
|
||||
//* Example:
|
||||
// switch (key)
|
||||
// {
|
||||
// case _T('K'): case VK_LEFT:
|
||||
// GAME_ENGINE->MessageBox("Moving left.");
|
||||
// break;
|
||||
// case _T('L'): case VK_DOWN:
|
||||
// GAME_ENGINE->MessageBox("Moving down.");
|
||||
// break;
|
||||
// case _T('M'): case VK_RIGHT:
|
||||
// GAME_ENGINE->MessageBox("Moving right.");
|
||||
// break;
|
||||
// case _T('O'): case VK_UP:
|
||||
// GAME_ENGINE->MessageBox("Moving up.");
|
||||
// break;
|
||||
// case VK_ESCAPE:
|
||||
// GAME_ENGINE->MessageBox("Escape menu.");
|
||||
// }
|
||||
|
||||
// switch(key){
|
||||
// case _T('W'):
|
||||
// GAME_ENGINE->MessageBox("W key pressed");
|
||||
// break;
|
||||
// }
|
||||
}
|
||||
|
||||
void Game::CallAction(Caller *callerPtr) {
|
||||
// Insert the code that needs to execute when a Caller (= Button, TextBox, Timer, Audio) executes an action
|
||||
}
|
||||
|
||||
void Game::InitialiseBindings() {
|
||||
std::cout << "Initialising bindings" << std::endl;
|
||||
m_state.open_libraries(sol::lib::base, sol::lib::package, sol::lib::string, sol::lib::table, sol::lib::math, sol::lib::os, sol::lib::io);
|
||||
|
||||
|
||||
m_state.new_usertype<ColorRGB>(
|
||||
"Color",
|
||||
sol::constructors<ColorRGB(float, float, float)>(),
|
||||
"r", &ColorRGB::r,
|
||||
"g", &ColorRGB::g,
|
||||
"b", &ColorRGB::b
|
||||
);
|
||||
|
||||
m_state.new_usertype<GameEngine>("GameEngine",
|
||||
"setTitle", &GameEngine::SetTitle,
|
||||
"setWidth", &GameEngine::SetWidth,
|
||||
"setHeight", &GameEngine::SetHeight,
|
||||
"getWidth", &GameEngine::GetWidth,
|
||||
"getHeight", &GameEngine::GetHeight,
|
||||
"setFrameRate", &GameEngine::SetFrameRate,
|
||||
"setWindowPosition", &GameEngine::SetWindowPosition,
|
||||
"setWindowRegion", &GameEngine::SetWindowRegion,
|
||||
"setKeyList", &GameEngine::SetKeyList,
|
||||
"setColor", &GameEngine::SetColorRGB,
|
||||
|
||||
"messageBox", [](GameEngine &gameEngine, const std::string &message) {
|
||||
gameEngine.MessageBox(message.c_str());
|
||||
},
|
||||
|
||||
"drawBitmap", sol::overload(
|
||||
sol::resolve<bool(const Bitmap*, int, int) const>(&GameEngine::DrawBitmap),
|
||||
sol::resolve<bool(const Bitmap*, int, int, RECT) const>(&GameEngine::DrawBitmap)
|
||||
),
|
||||
|
||||
"getMouseX", &GameEngine::GetMouseX,
|
||||
"getMouseY", &GameEngine::GetMouseY,
|
||||
"isMouseLeftDown", &GameEngine::IsMouseLeftDown,
|
||||
"isMouseRightDown", &GameEngine::IsMouseRightDown,
|
||||
|
||||
"drawRect", sol::overload(
|
||||
sol::resolve<bool(int, int, int, int) const>(&GameEngine::DrawRect),
|
||||
sol::resolve<bool(float, float, float, float) const>(&GameEngine::DrawRect)
|
||||
),
|
||||
"fillRect", sol::overload(
|
||||
sol::resolve<bool(int, int, int, int) const>(&GameEngine::FillRect),
|
||||
sol::resolve<bool(float, float, float, float) const>(&GameEngine::FillRect)
|
||||
),
|
||||
"drawOval", sol::overload(
|
||||
sol::resolve<bool(int, int, int, int) const>(&GameEngine::DrawOval),
|
||||
sol::resolve<bool(float, float, float, float) const>(&GameEngine::DrawOval)
|
||||
),
|
||||
"fillOval", sol::overload(
|
||||
sol::resolve<bool(int, int, int, int) const>(&GameEngine::FillOval),
|
||||
sol::resolve<bool(float, float, float, float) const>(&GameEngine::FillOval)
|
||||
),
|
||||
"fillScreen", &GameEngine::FillWindowRectRGB,
|
||||
"drawText", sol::overload(
|
||||
sol::resolve<int(const std::string &, int, int) const>(&GameEngine::DrawString),
|
||||
sol::resolve<int(const std::string &, float, float) const>(&GameEngine::DrawString)
|
||||
),
|
||||
"isKeyDown", [] (GameEngine &gameEngine, const std::string &key) {
|
||||
return gameEngine.IsKeyDown(_T(key[0]));
|
||||
},
|
||||
"getRequest", [](GameEngine &gameEngine, const std::string &url) {
|
||||
return gameEngine.GetRequest(url);
|
||||
},
|
||||
"postRequest", [](GameEngine &gameEngine, const std::string &url, const std::string &data) {
|
||||
return gameEngine.PostRequest(url, data);
|
||||
},
|
||||
"GetString", [](GameEngine &gameEngine) {
|
||||
return std::string(gameEngine.AskString());
|
||||
}
|
||||
);
|
||||
|
||||
m_state.new_usertype<Bitmap>(
|
||||
"Bitmap",
|
||||
sol::constructors<Bitmap(const tstring&, bool)>(),
|
||||
"SetTransparencyColor", [](Bitmap &bitmap, const ColorRGB &color) {
|
||||
bitmap.SetTransparencyColor(RGB(color.r, color.g, color.b));
|
||||
},
|
||||
"SetOpacity", &Bitmap::SetOpacity,
|
||||
"Exists", &Bitmap::Exists,
|
||||
"GetWidth", &Bitmap::GetWidth,
|
||||
"GetHeight", &Bitmap::GetHeight,
|
||||
"GetTransparencyColor", &Bitmap::GetTransparencyColor,
|
||||
"GetOpacity", &Bitmap::GetOpacity,
|
||||
"HasAlphaChannel", &Bitmap::HasAlphaChannel,
|
||||
"SaveToFile", &Bitmap::SaveToFile
|
||||
);
|
||||
m_state.new_usertype<TextBox>(
|
||||
"Textbox", sol::constructors<TextBox(const tstring&), TextBox()>(),
|
||||
"SetBounds", &TextBox::SetBounds,
|
||||
"SetText", &TextBox::SetText,
|
||||
"SetFont", &TextBox::SetFont,
|
||||
"SetBackcolor", &TextBox::SetBackcolor,
|
||||
"SetForecolor", &TextBox::SetForecolor,
|
||||
"SetEnabled", &TextBox::SetEnabled,
|
||||
"Show", &TextBox::Show,
|
||||
"Hide", &TextBox::Hide,
|
||||
"GetBounds", &TextBox::GetBounds,
|
||||
"GetText", &TextBox::GetText,
|
||||
"GetForecolor", &TextBox::GetForecolor
|
||||
);
|
||||
|
||||
m_state.set("GameEngine", GAME_ENGINE);
|
||||
}
|
||||
|
||||
//std::string Game::GetRequest(std::string url) {
|
||||
// cpr::Response r = cpr::Get(cpr::Url{url});
|
||||
// return r.text;
|
||||
//}
|
||||
|
||||
//
|
||||
//void Game::FunctionCall(const std::string &functionName) const {
|
||||
// auto func = m_state[functionName];
|
||||
// auto func_return{ func() };
|
||||
//
|
||||
// if (!func_return.valid()) {
|
||||
// //Handle Error
|
||||
// const sol::error err = func_return;
|
||||
// std::cerr << "Function Call Error: " << err.what();
|
||||
// GAME_ENGINE->MessageBox(err.what());
|
||||
// }
|
||||
// //Bram Verhulst - 2024
|
||||
//}
|
||||
|
||||
|
||||
|
||||
|
||||
94
src/Game.h
Normal file
@@ -0,0 +1,94 @@
|
||||
//-----------------------------------------------------------------
|
||||
// Main Game File
|
||||
// C++ Header - Game.h - version v8_01
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <sol/sol.hpp>
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// Include Files
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
#include "Resource.h"
|
||||
#include "GameEngine.h"
|
||||
#include "AbstractGame.h"
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// Game Class
|
||||
//-----------------------------------------------------------------
|
||||
class Game : public AbstractGame, public Callable
|
||||
{
|
||||
public:
|
||||
//---------------------------
|
||||
// Constructor(s) and Destructor
|
||||
//---------------------------
|
||||
Game(const std::string &fileName);
|
||||
|
||||
virtual ~Game() override;
|
||||
|
||||
//---------------------------
|
||||
// Disabling copy/move constructors and assignment operators
|
||||
//---------------------------
|
||||
Game(const Game& other) = delete;
|
||||
Game(Game&& other) noexcept = delete;
|
||||
Game& operator=(const Game& other) = delete;
|
||||
Game& operator=(Game&& other) noexcept = delete;
|
||||
|
||||
//---------------------------
|
||||
// General Member Functions
|
||||
//---------------------------
|
||||
void Initialize () override;
|
||||
void Start () override;
|
||||
void End () override;
|
||||
void Paint (RECT rect) const override;
|
||||
void Tick () override;
|
||||
void MouseButtonAction (bool isLeft, bool isDown, int x, int y, WPARAM wParam) override;
|
||||
void MouseWheelAction (int x, int y, int distance, WPARAM wParam) override;
|
||||
void MouseMove (int x, int y, WPARAM wParam) override;
|
||||
void CheckKeyboard () override;
|
||||
void KeyPressed (TCHAR key) override;
|
||||
|
||||
void CallAction (Caller* callerPtr) override;
|
||||
void InitialiseBindings () override;
|
||||
|
||||
// std::string GetRequest(std::string url);
|
||||
|
||||
template <typename ReturnType = void, typename... Args>
|
||||
ReturnType FunctionCall(const std::string &functionName, Args&&... args) const {
|
||||
auto func = m_state[functionName];
|
||||
sol::protected_function_result func_return;
|
||||
|
||||
if constexpr (sizeof...(Args) == 0) {
|
||||
func_return = func();
|
||||
} else {
|
||||
func_return = func(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
if (!func_return.valid()) {
|
||||
const sol::error err = func_return;
|
||||
std::cerr << "Function Call Error: " << err.what();
|
||||
GAME_ENGINE->MessageBox(err.what());
|
||||
throw std::runtime_error(err.what());
|
||||
}
|
||||
|
||||
if constexpr (!std::is_void_v<ReturnType>) {
|
||||
try {
|
||||
return func_return.get<ReturnType>();
|
||||
} catch (const sol::error& err) {
|
||||
std::cerr << "Return Value Error: " << err.what();
|
||||
GAME_ENGINE->MessageBox(err.what());
|
||||
}
|
||||
}
|
||||
|
||||
return ReturnType{};
|
||||
}
|
||||
private:
|
||||
// -------------------------
|
||||
// Datamembers
|
||||
// -------------------------
|
||||
|
||||
sol::state m_state;
|
||||
std::string m_fileName;
|
||||
};
|
||||
24
src/Game.rc
Normal file
@@ -0,0 +1,24 @@
|
||||
//-----------------------------------------------------------------
|
||||
// Game Skeleton Resources
|
||||
// RC Source - Game.rc - version v8_01
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// Include Files
|
||||
//-----------------------------------------------------------------
|
||||
#include "Resource.h"
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// Icons
|
||||
//-----------------------------------------------------------------
|
||||
IDI_BIG ICON "big.ico"
|
||||
IDI_SMALL ICON "small.ico"
|
||||
|
||||
IDD_NAME_DIALOG DIALOGEX 0, 0, 200, 100
|
||||
STYLE WS_CAPTION | WS_SYSMENU
|
||||
BEGIN
|
||||
LTEXT "Enter your name:", IDC_STATIC, 10, 10, 180, 10
|
||||
EDITTEXT IDC_NAME_EDIT, 10, 30, 180, 20, ES_AUTOHSCROLL
|
||||
PUSHBUTTON "OK", IDOK, 50, 60, 50, 14
|
||||
PUSHBUTTON "Cancel", IDCANCEL, 110, 60, 50, 14
|
||||
END
|
||||
85
src/GameDefines.h
Normal file
@@ -0,0 +1,85 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <tchar.h>
|
||||
|
||||
#ifdef _UNICODE // extra unicode defines
|
||||
#define tstring std::wstring
|
||||
#define tcin std::wcin
|
||||
#define tcout std::wcout
|
||||
#define tstringstream std::wstringstream
|
||||
#define tofstream std::wofstream
|
||||
#define tifstream std::wifstream
|
||||
#define tfstream std::wfstream
|
||||
#define tostream std::wostream
|
||||
#define to_tstring std::to_wstring
|
||||
#else
|
||||
#define tstring std::string
|
||||
#define tcin std::cin
|
||||
#define tcout std::cout
|
||||
#define tstringstream std::stringstream
|
||||
#define tofstream std::ofstream
|
||||
#define tifstream std::ifstream
|
||||
#define tfstream std::fstream
|
||||
#define tostream std::ostream
|
||||
#define to_tstring std::to_string
|
||||
#endif
|
||||
|
||||
//64 bit defines
|
||||
#ifdef _WIN64
|
||||
#define GWLA_WNDPROC GWLP_WNDPROC
|
||||
#define GWLA_HINSTANCE GWLP_HINSTANCE
|
||||
#define GWLA_HWNDPARENT GWLP_HWNDPARENT
|
||||
#define GWLA_USERDATA GWLP_USERDATA
|
||||
#else if
|
||||
#define GWLA_WNDPROC GWL_WNDPROC
|
||||
#define GWLA_HINSTANCE GWL_HINSTANCE
|
||||
#define GWLA_HWNDPARENT GWL_HWNDPARENT
|
||||
#define GWLA_USERDATA GWL_USERDATA
|
||||
#endif
|
||||
|
||||
// ASSERT macro
|
||||
#ifndef NDEBUG
|
||||
#ifdef _WIN64
|
||||
#define ASSERT \
|
||||
if ( false ) {} \
|
||||
else \
|
||||
struct LocalAssert { \
|
||||
int mLine{}; \
|
||||
LocalAssert(int line=__LINE__) : mLine(line) {} \
|
||||
LocalAssert(bool isOK, const TCHAR* message=_T("")) { \
|
||||
if ( !isOK ) { \
|
||||
tstringstream buffer; \
|
||||
buffer << _T("ERROR!! Assert failed on line ") << LocalAssert().mLine << _T(" in file '") << __FILE__ << _T("'\nMessage: \"") << message << _T("\"\n"); \
|
||||
OutputDebugString(buffer.str().c_str()); \
|
||||
} \
|
||||
} \
|
||||
} myAsserter = LocalAssert
|
||||
#else
|
||||
#define ASSERT \
|
||||
if ( false ) {} \
|
||||
else \
|
||||
struct LocalAssert { \
|
||||
int mLine{}; \
|
||||
LocalAssert(int line=__LINE__) : mLine(line) {} \
|
||||
LocalAssert(bool isOK, const TCHAR* message=_T("")) { \
|
||||
if ( !isOK ) { \
|
||||
tstringstream buffer; \
|
||||
buffer << _T("ERROR!! Assert failed on line ") << LocalAssert().mLine << _T(" in file '") << __FILE__ << _T("'\nMessage: \"") << message << _T("\"\n"); \
|
||||
OutputDebugString(buffer.str().c_str()); \
|
||||
__asm { int 3 } \
|
||||
} \
|
||||
} \
|
||||
} myAsserter = LocalAssert
|
||||
#endif
|
||||
#else
|
||||
#define ASSERT \
|
||||
if ( true ) {} else \
|
||||
struct NoAssert { \
|
||||
NoAssert(bool isOK, const TCHAR* message=_T("")) {} \
|
||||
} myAsserter = NoAssert
|
||||
#endif
|
||||
|
||||
2862
src/GameEngine.cpp
Normal file
773
src/GameEngine.h
Normal file
@@ -0,0 +1,773 @@
|
||||
//-----------------------------------------------------------------
|
||||
// Game Engine Object
|
||||
// C++ Header - GameEngine.h - version v8_01
|
||||
// 2006-2024 Kevin Hoefman - kevin.hoefman@howest.be
|
||||
//
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// Include Files
|
||||
//-----------------------------------------------------------------
|
||||
#define _WIN32_WINNT 0x0A00 // Windows 10 or 11
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define _WINSOCKAPI_
|
||||
#include <windows.h>
|
||||
#include <windowsx.h>
|
||||
#include <stdlib.h>
|
||||
#include <tchar.h>
|
||||
#include <Mmsystem.h> // winmm.lib header, used for playing sound
|
||||
#undef MessageBox
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <cpr/cpr.h>
|
||||
|
||||
#include <objidl.h> // GDI+ for PNG loading
|
||||
#include <gdiplus.h>
|
||||
#include <gdiplusinit.h>
|
||||
#include <gdiplusheaders.h>
|
||||
#include <GdiPlus.h>
|
||||
|
||||
#include "AbstractGame.h" // base for all games
|
||||
#include "GameDefines.h" // common header files and defines / macros
|
||||
|
||||
#include <vector> // using std::vector for tab control logic
|
||||
#include <queue> // using std::queue for event system
|
||||
#include <algorithm>
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// Pragma Library includes
|
||||
//-----------------------------------------------------------------
|
||||
#pragma comment(lib, "msimg32.lib") // used for transparency
|
||||
#pragma comment(lib, "winmm.lib") // used for sound
|
||||
#pragma comment(lib, "Gdiplus.lib") // used for PNG loading
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// GameEngine Forward Declarations
|
||||
//-----------------------------------------------------------------
|
||||
class Bitmap;
|
||||
class SoundWave;
|
||||
class Midi;
|
||||
class HitRegion;
|
||||
class Font;
|
||||
|
||||
struct ColorRGB{
|
||||
float r{};
|
||||
float g{};
|
||||
float b{};
|
||||
|
||||
ColorRGB() = default;
|
||||
ColorRGB(float r, float g, float b) : r(r), g(g), b(b) {}
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// GameEngine Class
|
||||
//-----------------------------------------------------------------
|
||||
class GameEngine
|
||||
{
|
||||
friend LRESULT CALLBACK WndProc(HWND hWindow, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
public:
|
||||
// Constructor and Destructor
|
||||
GameEngine();
|
||||
virtual ~GameEngine();
|
||||
|
||||
// Disabling copy/move constructors and assignment operators
|
||||
GameEngine(const GameEngine& other) = delete;
|
||||
GameEngine(GameEngine&& other) noexcept = delete;
|
||||
GameEngine& operator=(const GameEngine& other) = delete;
|
||||
GameEngine& operator=(GameEngine&& other) noexcept = delete;
|
||||
|
||||
// General Member Functions
|
||||
void SetGame (AbstractGame* gamePtr);
|
||||
bool Run (HINSTANCE hInstance, int cmdShow);
|
||||
|
||||
void SetTitle (const tstring& title); // SetTitle automatically sets the window class name
|
||||
void SetWindowPosition (int left, int top);
|
||||
bool SetWindowRegion (const HitRegion* regionPtr);
|
||||
void SetKeyList (const tstring& keyList);
|
||||
void SetFrameRate (int frameRate);
|
||||
void SetWidth (int width);
|
||||
void SetHeight (int height);
|
||||
|
||||
bool GoFullscreen ();
|
||||
bool GoWindowedMode ();
|
||||
void ShowMousePointer (bool value);
|
||||
void Quit ();
|
||||
|
||||
bool HasWindowRegion () const;
|
||||
bool IsFullscreen () const;
|
||||
|
||||
bool IsKeyDown (int vKey) const;
|
||||
|
||||
void MessageBox (const tstring& message) const;
|
||||
void MessageBox (const TCHAR* message) const;
|
||||
template <typename MyOtherType>
|
||||
void MessageBox (MyOtherType value) const { MessageBox(to_tstring(value)); }
|
||||
|
||||
bool MessageContinue (const tstring& message) const;
|
||||
|
||||
// Text Dimensions
|
||||
SIZE CalculateTextDimensions(const tstring& text, const Font* fontPtr) const;
|
||||
SIZE CalculateTextDimensions(const tstring& text, const Font* fontPtr, RECT rect) const;
|
||||
|
||||
// Draw Functions
|
||||
void SetColor (COLORREF color);
|
||||
void SetColorRGB (ColorRGB color);
|
||||
void SetFont (Font* fontPtr);
|
||||
|
||||
bool FillWindowRect (COLORREF color) const;
|
||||
bool FillWindowRectRGB (ColorRGB color) const;
|
||||
|
||||
bool DrawLine (int x1, int y1, int x2, int y2) const;
|
||||
|
||||
bool DrawRect (int left, int top, int width, int height) const;
|
||||
bool DrawRect (float left, float top, float width, float height) const;
|
||||
bool FillRect (int left, int top, int width, int height) const;
|
||||
bool FillRect (float left, float top, float width, float height) const;
|
||||
bool FillRectO (int left, int top, int right, int bottom, int opacity) const;
|
||||
bool DrawRoundRect (int left, int top, int right, int bottom, int radius) const;
|
||||
bool FillRoundRect (int left, int top, int right, int bottom, int radius) const;
|
||||
bool DrawOval (int left, int top, int width, int height) const;
|
||||
bool DrawOval (float left, float top, float width, float height) const;
|
||||
bool FillOval (int left, int top, int width, int height) const;
|
||||
bool FillOval (float left, float top, float width, float height) const;
|
||||
bool FillOval (int left, int top, int right, int bottom, int opacity) const;
|
||||
bool DrawArc (int left, int top, int right, int bottom, int startDegree, int angle) const;
|
||||
bool FillArc (int left, int top, int right, int bottom, int startDegree, int angle) const;
|
||||
|
||||
int DrawString (const tstring& text, int left, int top) const;
|
||||
int DrawString (const tstring& text, float left, float top) const;
|
||||
int DrawStringF (const tstring& text, int left, int top, int right, int bottom) const;
|
||||
|
||||
bool DrawBitmap (const Bitmap* bitmapPtr, int left, int top) const;
|
||||
bool DrawBitmap (const Bitmap* bitmapPtr, int left, int top, RECT sourceRect) const;
|
||||
|
||||
bool DrawPolygon (const POINT ptsArr[], int count) const;
|
||||
bool DrawPolygon (const POINT ptsArr[], int count, bool close) const;
|
||||
bool FillPolygon (const POINT ptsArr[], int count) const;
|
||||
bool FillPolygon (const POINT ptsArr[], int count, bool close) const;
|
||||
|
||||
COLORREF GetDrawColor () const;
|
||||
bool Repaint () const;
|
||||
|
||||
// Accessor Member Functions
|
||||
tstring GetTitle () const;
|
||||
HINSTANCE GetInstance () const { return m_Instance; }
|
||||
HWND GetWindow () const { return m_Window; }
|
||||
int GetWidth () const { return m_Width; }
|
||||
int GetHeight () const { return m_Height; }
|
||||
int GetFrameRate () const { return m_FrameRate; }
|
||||
int GetFrameDelay () const { return m_FrameDelay; }
|
||||
POINT GetWindowPosition () const;
|
||||
|
||||
// Tab control
|
||||
void TabNext (HWND ChildWindow) const;
|
||||
void TabPrevious (HWND ChildWindow) const;
|
||||
|
||||
int GetMouseX ();
|
||||
int GetMouseY ();
|
||||
|
||||
bool IsMouseLeftDown ();
|
||||
bool IsMouseRightDown ();
|
||||
|
||||
int GetControllersConnected() const;
|
||||
|
||||
std::string GetRequest(std::string url);
|
||||
std::string PostRequest(std::string url, std::string data);
|
||||
|
||||
const char* AskString();
|
||||
|
||||
private:
|
||||
// Private Member Functions
|
||||
LRESULT HandleEvent (HWND hWindow, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
bool CreateGameWindow (int cmdShow);
|
||||
void MonitorKeyboard ();
|
||||
|
||||
void SetInstance (HINSTANCE hInstance);
|
||||
void SetWindow (HWND hWindow);
|
||||
|
||||
void PaintDoubleBuffered (HDC hDC);
|
||||
void FormPolygon (const POINT ptsArr[], int count, bool close) const;
|
||||
POINT AngleToPoint (int left, int top, int right, int bottom, int angle) const;
|
||||
|
||||
// Member Variables
|
||||
HINSTANCE m_Instance {};
|
||||
HWND m_Window {};
|
||||
tstring m_Title {};
|
||||
int m_Width {};
|
||||
int m_Height {};
|
||||
int m_FrameRate { 50 };
|
||||
int m_FrameDelay { 1000 / m_FrameRate };
|
||||
bool m_RunGameLoop { true };
|
||||
TCHAR* m_KeyListPtr {};
|
||||
unsigned int m_KeybMonitor {};
|
||||
AbstractGame* m_GamePtr {};
|
||||
bool m_Fullscreen {};
|
||||
|
||||
// GDI+ for PNG loading
|
||||
ULONG_PTR m_GDIPlusToken;
|
||||
|
||||
// Draw assistance variables
|
||||
HDC m_HdcDraw {};
|
||||
RECT m_RectDraw {};
|
||||
bool m_IsPainting {};
|
||||
COLORREF m_ColDraw {};
|
||||
HFONT m_FontDraw {};
|
||||
|
||||
// Fullscreen assistance variable
|
||||
POINT m_OldPosition {};
|
||||
|
||||
// Window Region assistance variable
|
||||
HitRegion* m_WindowRegionPtr {};
|
||||
|
||||
int m_mouseX{};
|
||||
int m_mouseY{};
|
||||
|
||||
bool m_mouseLeftDown{};
|
||||
bool m_mouseRightDown{};
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------------------------
|
||||
// Callable Interface
|
||||
//
|
||||
// Interface implementation for classes that can be called by "caller" objects
|
||||
//------------------------------------------------------------------------------------------------
|
||||
class Caller; // forward declaration
|
||||
|
||||
class Callable
|
||||
{
|
||||
public:
|
||||
virtual ~Callable() = default; // virtual destructor for polymorphism
|
||||
|
||||
virtual void CallAction(Caller* callerPtr) = 0;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------------------------
|
||||
// Caller Base Class
|
||||
//
|
||||
// Base Clase implementation for up- and downcasting of "caller" objects: TextBox, Button, Timer, Audio and Video
|
||||
//------------------------------------------------------------------------------------------------
|
||||
class Caller
|
||||
{
|
||||
public:
|
||||
// -------------------------
|
||||
// Enums
|
||||
// -------------------------
|
||||
enum class Type
|
||||
{
|
||||
TextBox, Button, Timer, Audio, Video
|
||||
};
|
||||
|
||||
// -------------------------
|
||||
// Destructor
|
||||
// -------------------------
|
||||
virtual ~Caller() = default; // do not delete the targets!
|
||||
|
||||
// -------------------------
|
||||
// Disabling copy/move constructors and assignment operators
|
||||
// -------------------------
|
||||
Caller(const Caller& other) = delete;
|
||||
Caller(Caller&& other) noexcept = delete;
|
||||
Caller& operator=(const Caller& other) = delete;
|
||||
Caller& operator=(Caller&& other) noexcept = delete;
|
||||
|
||||
// -------------------------
|
||||
// General Member Functions
|
||||
// -------------------------
|
||||
virtual Type GetType() const = 0; // pure virtual function
|
||||
|
||||
virtual bool AddActionListener (Callable* targetPtr); // public interface method, call is passed on to private method
|
||||
virtual bool RemoveActionListener (const Callable* targetPtr); // public interface method, call is passed on to private method
|
||||
|
||||
protected:
|
||||
Caller() {} // constructor only for derived classes
|
||||
std::vector<Callable*> m_TargetList;
|
||||
|
||||
virtual bool CallListeners(); // placing the event code in a separate method instead of directly in the windows messaging
|
||||
// function allows inheriting classes to override the event code.
|
||||
|
||||
private:
|
||||
bool AddListenerObject (Callable* targetPtr);
|
||||
bool RemoveListenerObject (const Callable* targetPtr);
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Timer Class
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
class Timer : public Caller
|
||||
{
|
||||
public:
|
||||
// -------------------------
|
||||
// Constructor(s) and Destructor
|
||||
// -------------------------
|
||||
Timer(int msec, Callable* targetPtr, bool repeat = false);
|
||||
|
||||
virtual ~Timer() override;
|
||||
|
||||
// -------------------------
|
||||
// Disabling copy/move constructors and assignment operators
|
||||
// -------------------------
|
||||
Timer(const Timer& other) = delete;
|
||||
Timer(Timer&& other) noexcept = delete;
|
||||
Timer& operator=(const Timer& other) = delete;
|
||||
Timer& operator=(Timer&& other) noexcept = delete;
|
||||
|
||||
// -------------------------
|
||||
// General Member Functions
|
||||
// -------------------------
|
||||
void Start ();
|
||||
void Stop ();
|
||||
void SetDelay (int msec);
|
||||
void SetRepeat (bool repeat);
|
||||
|
||||
bool IsRunning () const;
|
||||
int GetDelay () const;
|
||||
Type GetType () const;
|
||||
|
||||
private:
|
||||
// -------------------------
|
||||
// Datamembers
|
||||
// -------------------------
|
||||
HANDLE m_TimerHandle {};
|
||||
bool m_IsRunning {};
|
||||
bool m_MustRepeat;
|
||||
int m_Delay;
|
||||
|
||||
// -------------------------
|
||||
// Handler functions
|
||||
// -------------------------
|
||||
static void CALLBACK TimerProcStatic(void* lpParameter, BOOLEAN TimerOrWaitFired); // proc will call CallListeners()
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// TextBox Class
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
class TextBox : public Caller
|
||||
{
|
||||
public:
|
||||
// -------------------------
|
||||
// Constructor(s) and Destructor
|
||||
// -------------------------
|
||||
TextBox(const tstring& text);
|
||||
TextBox();
|
||||
|
||||
virtual ~TextBox() override;
|
||||
|
||||
// -------------------------
|
||||
// Disabling copy/move constructors and assignment operators
|
||||
// -------------------------
|
||||
TextBox(const TextBox& other) = delete;
|
||||
TextBox(TextBox&& other) noexcept = delete;
|
||||
TextBox& operator=(const TextBox& other) = delete;
|
||||
TextBox& operator=(TextBox&& other) noexcept = delete;
|
||||
|
||||
// -------------------------
|
||||
// General Member Functions
|
||||
// -------------------------
|
||||
void SetBounds (int left, int top, int width, int height);
|
||||
void SetText (const tstring& text);
|
||||
void SetFont (const tstring& fontName, bool bold, bool italic, bool underline, int size);
|
||||
void SetBackcolor (COLORREF color);
|
||||
void SetForecolor (COLORREF color);
|
||||
void SetEnabled (bool enable);
|
||||
void Show ();
|
||||
void Hide ();
|
||||
|
||||
RECT GetBounds () const;
|
||||
tstring GetText () const;
|
||||
COLORREF GetForecolor () const;
|
||||
COLORREF GetBackcolor () const;
|
||||
HBRUSH GetBackcolorBrush () const;
|
||||
Type GetType () const;
|
||||
|
||||
private:
|
||||
// -------------------------
|
||||
// Member Functions
|
||||
// -------------------------
|
||||
void Repaint ();
|
||||
void Update ();
|
||||
|
||||
// -------------------------
|
||||
// Datamembers
|
||||
// -------------------------
|
||||
RECT m_Bounds { 0, 0, 100, 25 };
|
||||
HWND m_WndEdit {};
|
||||
WNDPROC m_ProcOldEdit {};
|
||||
COLORREF m_BgColor { RGB(255, 255, 255) };
|
||||
COLORREF m_ForeColor {};
|
||||
HBRUSH m_BgColorBrush {};
|
||||
HFONT m_Font {};
|
||||
HFONT m_OldFont {};
|
||||
|
||||
// -------------------------
|
||||
// Handler functions
|
||||
// -------------------------
|
||||
static LRESULT CALLBACK EditProcStatic(HWND hWindow, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
LRESULT EditProc(HWND hWindow, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// Button Class
|
||||
//-----------------------------------------------------------------
|
||||
class Button : public Caller
|
||||
{
|
||||
public:
|
||||
// -------------------------
|
||||
// Constructor(s) and Destructor
|
||||
// -------------------------
|
||||
Button(const tstring& label);
|
||||
Button();
|
||||
|
||||
virtual ~Button() override;
|
||||
|
||||
// -------------------------
|
||||
// Disabling copy/move constructors and assignment operators
|
||||
// -------------------------
|
||||
Button(const Button& other) = delete;
|
||||
Button(Button&& other) noexcept = delete;
|
||||
Button& operator=(const Button& other) = delete;
|
||||
Button& operator=(Button&& other) noexcept = delete;
|
||||
|
||||
// -------------------------
|
||||
// General Member Functions
|
||||
// -------------------------
|
||||
void SetBounds (int left, int top, int right, int bottom);
|
||||
void SetText (const tstring& text);
|
||||
void SetFont (const tstring& fontName, bool bold, bool italic, bool underline, int size);
|
||||
void SetEnabled (bool enable);
|
||||
void Show ();
|
||||
void Hide ();
|
||||
|
||||
RECT GetBounds () const;
|
||||
tstring GetText () const;
|
||||
Type GetType () const;
|
||||
|
||||
private:
|
||||
// -------------------------
|
||||
// Member Functions
|
||||
// -------------------------
|
||||
void Update();
|
||||
|
||||
// -------------------------
|
||||
// Datamembers
|
||||
// -------------------------
|
||||
RECT m_Bounds { 0, 0, 100, 25 };
|
||||
HWND m_WndButton {};
|
||||
WNDPROC m_ProcOldButton {};
|
||||
bool m_Armed {};
|
||||
HFONT m_Font {};
|
||||
HFONT m_OldFont {};
|
||||
|
||||
// -------------------------
|
||||
// Handler functions
|
||||
// -------------------------
|
||||
static LRESULT CALLBACK ButtonProcStatic(HWND hWindow, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
LRESULT ButtonProc(HWND hWindow, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// Audio Class
|
||||
//-----------------------------------------------------------------
|
||||
class Audio : public Caller
|
||||
{
|
||||
public:
|
||||
// -------------------------
|
||||
// Constructor(s) and Destructor
|
||||
// -------------------------
|
||||
Audio(const tstring& filename);
|
||||
//Audio(int IDAudio, const tstring& type);
|
||||
|
||||
virtual ~Audio() override;
|
||||
|
||||
// -------------------------
|
||||
// Disabling copy/move constructors and assignment operators
|
||||
// -------------------------
|
||||
Audio(const Audio& other) = delete;
|
||||
Audio(Audio&& other) noexcept = delete;
|
||||
Audio& operator=(const Audio& other) = delete;
|
||||
Audio& operator=(Audio&& other) noexcept = delete;
|
||||
|
||||
// -------------------------
|
||||
// General member functions
|
||||
// -------------------------
|
||||
// Commands are queued, and only sent when Tick() is called. Calling Tick() needs to be done on the main thread (mcisendstring isn't thread safe)
|
||||
void Tick ();
|
||||
|
||||
void Play (int msecStart = 0, int msecStop = -1);
|
||||
void Pause ();
|
||||
void Stop ();
|
||||
void SetVolume (int volume);
|
||||
void SetRepeat (bool repeat);
|
||||
|
||||
const tstring& GetName () const;
|
||||
const tstring& GetAlias () const;
|
||||
int GetDuration () const;
|
||||
bool IsPlaying () const;
|
||||
bool IsPaused () const;
|
||||
bool GetRepeat () const;
|
||||
bool Exists () const;
|
||||
int GetVolume () const;
|
||||
Type GetType () const;
|
||||
|
||||
private:
|
||||
// -------------------------
|
||||
// Datamembers
|
||||
// -------------------------
|
||||
static int m_Nr;
|
||||
|
||||
tstring m_Filename;
|
||||
tstring m_Alias;
|
||||
bool m_Playing {};
|
||||
bool m_Paused {};
|
||||
bool m_MustRepeat {};
|
||||
HWND m_hWnd {};
|
||||
int m_Duration { -1 };
|
||||
int m_Volume { 100 };
|
||||
|
||||
// -------------------------
|
||||
// General Member Functions
|
||||
// -------------------------
|
||||
void Create(const tstring& filename);
|
||||
void Extract(WORD id, const tstring& type, const tstring& filename) const;
|
||||
void SwitchPlayingOff();
|
||||
|
||||
// -------------------------
|
||||
// Private mcisendstring command member functions and command queue datamember
|
||||
// -------------------------
|
||||
std::queue<tstring> m_CommandQueue;
|
||||
|
||||
void QueuePlayCommand (int msecStart);
|
||||
void QueuePlayCommand (int msecStart, int msecStop);
|
||||
void QueuePauseCommand ();
|
||||
void QueueResumeCommand ();
|
||||
void QueueStopCommand ();
|
||||
void QueueVolumeCommand (int volume);
|
||||
void QueueCommand (const tstring& command);
|
||||
|
||||
void SendMCICommand (const tstring& command);
|
||||
|
||||
//void QueuePositionCommand(int x, int y);
|
||||
|
||||
// -------------------------
|
||||
// Handler functions
|
||||
// -------------------------
|
||||
static LRESULT CALLBACK AudioProcStatic(HWND hWindow, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// Bitmap Class
|
||||
//-----------------------------------------------------------------
|
||||
class Bitmap final
|
||||
{
|
||||
public:
|
||||
// -------------------------
|
||||
// Constructor(s) and Destructor
|
||||
// -------------------------
|
||||
Bitmap(const tstring& filename, bool createAlphaChannel = true);
|
||||
//Bitmap(HBITMAP hBitmap);
|
||||
//Bitmap(int IDBitmap, const tstring& type, bool createAlphaChannel = true);
|
||||
|
||||
~Bitmap();
|
||||
|
||||
// -------------------------
|
||||
// Disabling copy/move constructors and assignment operators
|
||||
// -------------------------
|
||||
Bitmap(const Bitmap& other) = delete;
|
||||
Bitmap(Bitmap&& other) noexcept = delete;
|
||||
Bitmap& operator=(const Bitmap& other) = delete;
|
||||
Bitmap& operator=(Bitmap&& other) noexcept = delete;
|
||||
|
||||
// -------------------------
|
||||
// General Member Functions
|
||||
// -------------------------
|
||||
void SetTransparencyColor (COLORREF color);
|
||||
void SetOpacity (int);
|
||||
|
||||
bool Exists () const;
|
||||
int GetWidth () const;
|
||||
int GetHeight () const;
|
||||
COLORREF GetTransparencyColor () const;
|
||||
int GetOpacity () const;
|
||||
bool HasAlphaChannel () const;
|
||||
bool SaveToFile (const tstring& filename) const;
|
||||
|
||||
HBITMAP GetHandle () const;
|
||||
|
||||
private:
|
||||
// -------------------------
|
||||
// Datamembers
|
||||
// -------------------------
|
||||
static int m_Nr;
|
||||
|
||||
HBITMAP m_hBitmap {};
|
||||
COLORREF m_TransparencyKey {};
|
||||
int m_Opacity { 100 };
|
||||
unsigned char* m_PixelsPtr {};
|
||||
bool m_HasAlphaChannel;
|
||||
|
||||
// -------------------------
|
||||
// Member Functions
|
||||
// -------------------------
|
||||
HBITMAP LoadPNG(TCHAR* pFilePath);
|
||||
void CreateAlphaChannel();
|
||||
void Extract(WORD id, const tstring& type, const tstring& fileName) const;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// HitRegion Class
|
||||
//-----------------------------------------------------------------
|
||||
class HitRegion final
|
||||
{
|
||||
public:
|
||||
// -------------------------
|
||||
// Enums
|
||||
// -------------------------
|
||||
enum class Shape
|
||||
{
|
||||
Ellipse, Rectangle
|
||||
};
|
||||
|
||||
//---------------------------
|
||||
// Constructor(s) and Destructor
|
||||
//---------------------------
|
||||
HitRegion(Shape shape, int left, int top, int right, int bottom); // Use this create to form a rectangular or elliptic hitregion
|
||||
HitRegion(const POINT* pointsArr, int numberOfPoints); // Use this create to form a polygonal hitregion
|
||||
HitRegion(const Bitmap* bmpPtr, COLORREF cTransparent = RGB(255, 0, 255), COLORREF cTolerance = 0); // Use this create to create a hitregion from a bitmap
|
||||
|
||||
~HitRegion();
|
||||
|
||||
//---------------------------
|
||||
// Implementing copy/move constructors, disabling assignment operators
|
||||
//---------------------------
|
||||
HitRegion(const HitRegion& other);
|
||||
HitRegion(HitRegion&& other) noexcept;
|
||||
HitRegion& operator=(const HitRegion& other) = delete;
|
||||
HitRegion& operator=(HitRegion&& other) noexcept = delete;
|
||||
|
||||
//---------------------------
|
||||
// General Member Functions
|
||||
//---------------------------
|
||||
void Move (int deltaX, int deltaY); // Moves the region over the given displacement
|
||||
|
||||
bool HitTest (int x, int y) const; // Returns true if the point that corresponds to the given x- and y-values is in the region, false if not
|
||||
bool HitTest (const HitRegion* regionPtr) const; // Returns true if the regions overlap, false if they don't
|
||||
|
||||
POINT CollisionTest (const HitRegion* regionPtr) const; // Returns {-1000000, -1000000} if the regions don't overlap, and the center point of the overlapping region if they do overlap
|
||||
// CollisionTest is useful to determine the hitting point of two forms that barely touch
|
||||
|
||||
RECT GetBounds () const; // Returns the position + width and height of the smallest rectangle that encloses this region (in case of a rectangular region: the region itself)
|
||||
|
||||
bool Exists () const; // Returns true if the hitregion was successfully created, false if not
|
||||
|
||||
HRGN GetHandle () const; // Returns the handle of the region (Win32 stuff)
|
||||
|
||||
private:
|
||||
//---------------------------
|
||||
// Datamembers
|
||||
//---------------------------
|
||||
HRGN m_HitRegion {}; // The region data is stored by means of a Win32 "region" resources (not for 1st semester)
|
||||
|
||||
//---------------------------
|
||||
// Private Member Functions
|
||||
//---------------------------
|
||||
HRGN BitmapToRegion(HBITMAP hBmp, COLORREF cTransparentColor, COLORREF cTolerance) const;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// Font Class
|
||||
//-----------------------------------------------------------------
|
||||
class Font final
|
||||
{
|
||||
public:
|
||||
//---------------------------
|
||||
// Constructor(s) and Destructor
|
||||
//---------------------------
|
||||
Font(const tstring& fontName, bool bold, bool italic, bool underline, int size);
|
||||
|
||||
~Font();
|
||||
|
||||
//---------------------------
|
||||
// Disabling copy/move constructors and assignment operators
|
||||
//---------------------------
|
||||
Font(const Font& other) = delete;
|
||||
Font(Font&& other) noexcept = delete;
|
||||
Font& operator=(const Font& other) = delete;
|
||||
Font& operator=(Font&& other) noexcept = delete;
|
||||
|
||||
//---------------------------
|
||||
// General Member Functions
|
||||
//---------------------------
|
||||
HFONT GetHandle() const;
|
||||
|
||||
private:
|
||||
//---------------------------
|
||||
// Datamembers
|
||||
//---------------------------
|
||||
HFONT m_Font;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// Exception Classes
|
||||
//-----------------------------------------------------------------
|
||||
class BadFilenameException final
|
||||
{
|
||||
public:
|
||||
BadFilenameException(const tstring& filename);
|
||||
tstring GetMessage();
|
||||
|
||||
private:
|
||||
tstring m_Filename;
|
||||
};
|
||||
|
||||
class FileNotFoundException final
|
||||
{
|
||||
public:
|
||||
FileNotFoundException(const tstring& filename);
|
||||
tstring GetMessage();
|
||||
|
||||
private:
|
||||
tstring m_Filename;
|
||||
};
|
||||
|
||||
class UnsupportedFormatException final
|
||||
{
|
||||
public:
|
||||
UnsupportedFormatException(const tstring& filename);
|
||||
tstring GetMessage();
|
||||
|
||||
private:
|
||||
tstring m_Filename;
|
||||
};
|
||||
|
||||
class CouldNotLoadFileException final
|
||||
{
|
||||
public:
|
||||
CouldNotLoadFileException(const tstring& filename);
|
||||
tstring GetMessage();
|
||||
|
||||
private:
|
||||
tstring m_Filename;
|
||||
};
|
||||
|
||||
class BitmapNotLoadedException final {};
|
||||
class CouldNotCreateHitregionFromBitmapException final {};
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// Extra OutputDebugString functions
|
||||
//-----------------------------------------------------------------
|
||||
void OutputDebugString(const tstring& text);
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// Windows Procedure Declarations
|
||||
//-----------------------------------------------------------------
|
||||
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// Extern declaration for GAME_ENGINE global (singleton) object and pointer
|
||||
//-----------------------------------------------------------------
|
||||
extern GameEngine myGameEngine;
|
||||
extern GameEngine* GAME_ENGINE;
|
||||
81
src/GameWinMain.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
//-----------------------------------------------------------------
|
||||
// Game Engine WinMain Function
|
||||
// C++ Source - GameWinMain.cpp - version v8_01
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// Include Files
|
||||
//-----------------------------------------------------------------
|
||||
#define _WIN32_WINNT 0x0A00 // Windows 10 or 11
|
||||
#define _WINSOCKAPI_
|
||||
#include <windows.h>
|
||||
#include <windowsx.h>
|
||||
#include <stdlib.h>
|
||||
#include <tchar.h>
|
||||
#include <Mmsystem.h> // winmm.lib header, used for playing sound
|
||||
#undef MessageBox
|
||||
|
||||
#include "GameWinMain.h"
|
||||
#include "GameEngine.h"
|
||||
|
||||
#include "Game.h"
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// Create GAME_ENGINE global (singleton) object and pointer
|
||||
//-----------------------------------------------------------------
|
||||
GameEngine myGameEngine;
|
||||
GameEngine* GAME_ENGINE{ &myGameEngine };
|
||||
|
||||
|
||||
void AllocateConsole()
|
||||
{
|
||||
if (AllocConsole()) // Allocate a new console for the application
|
||||
{
|
||||
FILE *fp; // Redirect STDOUT to the console
|
||||
freopen_s(&fp, "CONOUT$", "w", stdout);
|
||||
setvbuf(stdout, NULL, _IONBF, 0); // Disable buffering for stdout
|
||||
|
||||
freopen_s(&fp, "CONOUT$", "w", stderr); // Redirect STDERR to the console
|
||||
setvbuf(stderr, NULL, _IONBF, 0); // Disable buffering for stderr
|
||||
|
||||
freopen_s(&fp, "CONIN$", "r", stdin); // Redirect STDIN to the console
|
||||
setvbuf(stdin, NULL, _IONBF, 0); // Disable buffering for stdin
|
||||
|
||||
std::ios::sync_with_stdio(true); // Sync C++ streams with the console
|
||||
}
|
||||
}
|
||||
|
||||
std::string WStringToString(const std::wstring& wstr) {
|
||||
if (wstr.empty()) return {};
|
||||
|
||||
int size_needed = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, nullptr, 0, nullptr, nullptr);
|
||||
std::string str(size_needed - 1, '\0');
|
||||
WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, &str[0], size_needed, nullptr, nullptr);
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// Main Function
|
||||
//-----------------------------------------------------------------
|
||||
int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow)
|
||||
{
|
||||
AllocateConsole();
|
||||
|
||||
int argc{ 1 };
|
||||
LPWSTR* argv = CommandLineToArgvW(GetCommandLineW(), &argc);
|
||||
|
||||
if(argc == 2){
|
||||
//We dragged and Dropped a lua file on us
|
||||
std::string convertedString{WStringToString(argv[1])};
|
||||
GAME_ENGINE->SetGame(new Game(convertedString)); // any class that implements AbstractGame
|
||||
|
||||
} else {
|
||||
GAME_ENGINE->SetGame(new Game("./lua/script.lua")); // any class that implements AbstractGame
|
||||
}
|
||||
|
||||
|
||||
return GAME_ENGINE->Run(hInstance, nCmdShow); // here we go
|
||||
|
||||
}
|
||||
|
||||
17
src/GameWinMain.h
Normal file
@@ -0,0 +1,17 @@
|
||||
//-----------------------------------------------------------------
|
||||
// Game Engine WinMain Function
|
||||
// C++ Header - GameWinMain.h - version v8_01
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// Include Files
|
||||
//-----------------------------------------------------------------
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// Windows Function Declarations
|
||||
//-----------------------------------------------------------------
|
||||
int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow);
|
||||
BIN
src/big.ico
Normal file
|
After Width: | Height: | Size: 23 KiB |
10
src/resource.h
Normal file
@@ -0,0 +1,10 @@
|
||||
//-----------------------------------------------------------------
|
||||
// Game Skeleton Resource Identifiers
|
||||
// C++ Header - Resource.h - version v7_02_firstyear
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// Icons Range : 1000 - 1999
|
||||
//-----------------------------------------------------------------
|
||||
#define IDI_BIG 1000
|
||||
#define IDI_SMALL 1001
|
||||
BIN
src/small.ico
Normal file
|
After Width: | Height: | Size: 23 KiB |