Compare commits
8 Commits
bugfix/phy
...
feature/ph
| Author | SHA1 | Date | |
|---|---|---|---|
|
462fb12bd5
|
|||
|
cb878cfaa5
|
|||
|
71de95822c
|
|||
|
f4728bf19d
|
|||
|
42453c2eb6
|
|||
|
652ee4cdf3
|
|||
|
9fed59c4c8
|
|||
|
941eeb2493
|
@@ -69,10 +69,13 @@ add_library(akgl SHARED
|
||||
src/heap.c
|
||||
src/json_helpers.c
|
||||
src/registry.c
|
||||
src/renderer.c
|
||||
src/physics.c
|
||||
src/sprite.c
|
||||
src/staticstring.c
|
||||
src/tilemap.c
|
||||
src/util.c
|
||||
src/stage.c
|
||||
${GAMECONTROLLERDB_H}
|
||||
)
|
||||
|
||||
@@ -142,6 +145,8 @@ install(FILES "include/akgl/controller.h" DESTINATION "include/akgl/")
|
||||
install(FILES "include/akgl/heap.h" DESTINATION "include/akgl/")
|
||||
install(FILES "include/akgl/iterator.h" DESTINATION "include/akgl/")
|
||||
install(FILES "include/akgl/json_helpers.h" DESTINATION "include/akgl/")
|
||||
install(FILES "include/akgl/renderer.h" DESTINATION "include/akgl/")
|
||||
install(FILES "include/akgl/physics.h" DESTINATION "include/akgl/")
|
||||
install(FILES "include/akgl/registry.h" DESTINATION "include/akgl/")
|
||||
install(FILES "include/akgl/sprite.h" DESTINATION "include/akgl/")
|
||||
install(FILES "include/akgl/staticstring.h" DESTINATION "include/akgl/")
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#ifndef _SDL_GAMECONTROLLERDB_H_
|
||||
#define _SDL_GAMECONTROLLERDB_H_
|
||||
|
||||
// Taken from https://raw.githubusercontent.com/mdqinc/SDL_GameControllerDB/refs/heads/master/gamecontrollerdb.txt on Tue May 26 10:27:58 AM EDT 2026
|
||||
// Taken from https://raw.githubusercontent.com/mdqinc/SDL_GameControllerDB/refs/heads/master/gamecontrollerdb.txt on Sat Jun 27 08:22:48 AM EDT 2026
|
||||
|
||||
#define AKGL_SDL_GAMECONTROLLER_DB_LEN 2228
|
||||
#define AKGL_SDL_GAMECONTROLLER_DB_LEN 2243
|
||||
|
||||
const char *SDL_GAMECONTROLLER_DB[] = {
|
||||
"03000000300f00000a01000000000000,3 In 1 Conversion Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b8,x:b3,y:b0,platform:Windows",
|
||||
@@ -687,7 +687,7 @@ const char *SDL_GAMECONTROLLER_DB[] = {
|
||||
"03000000a306000020f6000000000000,Saitek PS2700 PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows",
|
||||
"03000000300f00001101000000000000,Saitek Rumble,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows",
|
||||
"03000000e804000000a0000000000000,Samsung EIGP20,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows",
|
||||
"03000000bd12000010d1000000000000,Sanwa 4Button,a:b0,b:b1,x:b2,y:b3,dpup:-a1,dpdown:+a1,dpleft:-a0,dpright:+a0,platform:Windows",
|
||||
"03000000bd12000010d1000000000000,Sanwa 4Button,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,x:b2,y:b3,platform:Windows",
|
||||
"03000000c01100000252000000000000,Sanwa Easy Grip,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows",
|
||||
"03000000c01100004350000000000000,Sanwa Micro Grip P3,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,x:b3,y:b2,platform:Windows",
|
||||
"03000000411200004550000000000000,Sanwa Micro Grip Pro,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a1,righty:a2,start:b9,x:b1,y:b3,platform:Windows",
|
||||
@@ -701,14 +701,14 @@ const char *SDL_GAMECONTROLLER_DB[] = {
|
||||
"030000004f04000028b3000000000000,Score A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows",
|
||||
"03000000952e00002577000000000000,Scuf PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows",
|
||||
"03000000a30c00002500000000000000,Sega Genesis Mini 3B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,righttrigger:b5,start:b9,platform:Windows",
|
||||
"03000000a30c00002400000000000000,Sega Mega Drive Mini 6B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,rightshoulder:b4,righttrigger:b5,leftshoulder:b6,lefttrigger:b7,back:b8,start:b9,x:b3,y:b0,platform:Windows",
|
||||
"03000000a30c00002400000000000000,Sega Mega Drive Mini 6B Controller,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows",
|
||||
"03000000d804000086e6000000000000,Sega Multi Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:a2,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows",
|
||||
"0300000000050000289b000000000000,Sega Saturn Adapter,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows",
|
||||
"0300000000f000000800000000000000,Sega Saturn Controller,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b7,righttrigger:b3,start:b0,x:b5,y:b6,platform:Windows",
|
||||
"03000000730700000601000000000000,Sega Saturn Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows",
|
||||
"03000000b40400000a01000000000000,Sega Saturn Controller,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows",
|
||||
"030000003b07000004a1000000000000,SFX,a:b0,b:b2,back:b7,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b5,start:b8,x:b1,y:b3,platform:Windows",
|
||||
"03000000632500002705000000000000,ShanWan Q36,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,righttrigger:b9,start:b11,x:b3,y:b4,platform:Windows",
|
||||
"03000000632500002705000000000000,ShanWan Gamepad,+lefty:+a2,-lefty:-a1,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,rightshoulder:b7,rightstick:b14,righttrigger:b9,start:b11,x:b3,y:b4,platform:Windows",
|
||||
"03000000f82100001900000000000000,Shogun Bros Chameleon X1,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows",
|
||||
"03000000120c00001c1e000000000000,SnakeByte 4S PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows",
|
||||
"03000000140300000918000000000000,SNES Controller,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows",
|
||||
@@ -737,6 +737,7 @@ const char *SDL_GAMECONTROLLER_DB[] = {
|
||||
"03000000120c0000160e000000000000,Steel Play Metaltech PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows",
|
||||
"03000000110100001914000000000000,SteelSeries,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightstick:b14,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows",
|
||||
"03000000381000001214000000000000,SteelSeries Free,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows",
|
||||
"03000000381000004114000000000000,SteelSeries Nimbus Cloud,a:b0,b:b1,x:b3,y:b4,back:b10,guide:b15,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,paddle1:b5,paddle2:b2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b8,righttrigger:b9,platform:Windows",
|
||||
"03000000110100003114000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows",
|
||||
"03000000381000003014000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows",
|
||||
"03000000381000003114000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows",
|
||||
@@ -780,6 +781,7 @@ const char *SDL_GAMECONTROLLER_DB[] = {
|
||||
"030000005f140000c501000000000000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows",
|
||||
"03000000b80500000210000000000000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows",
|
||||
"030000005f1400002a01000000000000,Trust Predator GM1200,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,x:b3,y:b4,platform:Windows",
|
||||
"03000000580400000a10000000000000,Trust Sight Fighter,a:b0,b:b1,back:b5,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,start:b2,x:b3,y:b4,platform:Windows",
|
||||
"030000004f04000087b6000000000000,TWCS Throttle,dpdown:b8,dpleft:b9,dpright:b7,dpup:b6,leftstick:b5,lefttrigger:-a5,leftx:a0,lefty:a1,righttrigger:+a5,platform:Windows",
|
||||
"03000000411200000450000000000000,Twin Shock,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a4,start:b11,x:b3,y:b0,platform:Windows",
|
||||
"03000000d90400000200000000000000,TwinShock PS2 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows",
|
||||
@@ -941,6 +943,7 @@ const char *SDL_GAMECONTROLLER_DB[] = {
|
||||
"03000000503200000110000045010000,Atari VCS Classic,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b3,start:b2,platform:Mac OS X",
|
||||
"03000000503200000110000047010000,Atari VCS Classic Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b3,start:b2,platform:Mac OS X",
|
||||
"03000000503200000210000047010000,Atari VCS Modern Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a2,righty:a3,start:b8,x:b2,y:b3,platform:Mac OS X",
|
||||
"03000000e30500008106000000010000,Austgame GameCube Adapter,a:b0,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:+a4,leftx:a0,lefty:a1,misc3:b5,misc4:b6,rightshoulder:b4,righttrigger:-a4,rightx:a2,righty:a3,start:b7,x:b1,y:b3,platform:Mac OS X",
|
||||
"030000008a3500000102000000010000,Backbone One,a:b0,b:b1,back:b16,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b17,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b15,x:b2,y:b3,platform:Mac OS X",
|
||||
"030000008a3500000201000000010000,Backbone One,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X",
|
||||
"030000008a3500000202000000010000,Backbone One,a:b0,b:b1,back:b16,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b17,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b15,x:b2,y:b3,platform:Mac OS X",
|
||||
@@ -1118,6 +1121,7 @@ const char *SDL_GAMECONTROLLER_DB[] = {
|
||||
"03000000110100002014000000000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X",
|
||||
"03000000110100002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X",
|
||||
"03000000381000002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X",
|
||||
"03000000381000004114000000010000,SteelSeries Nimbus Cloud,a:b0,b:b1,x:b3,y:b4,back:b10,guide:b15,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,paddle1:b5,paddle2:b2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4,platform:Mac OS X",
|
||||
"05000000484944204465766963650000,SteelSeries Nimbus Plus,a:b0,b:b1,back:b15,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b14,x:b2,y:b3,platform:Mac OS X",
|
||||
"050000004e696d6275732b0000000000,SteelSeries Nimbus Plus,a:b0,b:b1,back:b15,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b14,x:b2,y:b3,platform:Mac OS X",
|
||||
"03000000381000003014000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X",
|
||||
@@ -1249,12 +1253,16 @@ const char *SDL_GAMECONTROLLER_DB[] = {
|
||||
"03000000c82d00001230000011010000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux",
|
||||
"03000000c82d00001330000011010000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux",
|
||||
"05000000c82d00001230000000010000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux",
|
||||
"03000000c82d00001260000011010000,8BitDo Ultimate 2,a:b0,b:b1,x:b3,y:b4,back:b10,guide:b12,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,paddle1:b17,paddle2:b16,paddle3:b2,paddle4:b5,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4,platform:Linux",
|
||||
"03000000c82d00000b31000014010000,8BitDo Ultimate 2,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b8,start:b7,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux",
|
||||
"05000000c82d00001260000001000000,8BitDo Ultimate 2,a:b0,b:b1,x:b3,y:b4,back:b10,guide:b12,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,paddle1:b17,paddle2:b16,paddle3:b2,paddle4:b5,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4,platform:Linux",
|
||||
"03000000c82d00000a31000014010000,8BitDo Ultimate 2C,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux",
|
||||
"03000000c82d00001d30000011010000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux",
|
||||
"05000000c82d00001b30000001000000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux",
|
||||
"03000000c82d00001530000011010000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux",
|
||||
"03000000c82d00001630000011010000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux",
|
||||
"03000000c82d00001730000011010000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux",
|
||||
"06000000c82d00000320000007010000,8BitDo Ultimate Wired Controller for Xbox,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b8,start:b7,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux",
|
||||
"03000000c82d00000121000011010000,8BitDo Xbox One SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux",
|
||||
"05000000c82d00000121000000010000,8BitDo Xbox One SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux",
|
||||
"05000000a00500003232000001000000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux",
|
||||
@@ -1276,6 +1284,7 @@ const char *SDL_GAMECONTROLLER_DB[] = {
|
||||
"03000000020500000913000010010000,Anbernic RG P01,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux",
|
||||
"03000000373500000710000010010000,Anbernic RG P01,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux",
|
||||
"05000000373500004610000001000000,Anbernic RG P01,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux",
|
||||
"19000000010000000100000000010000,Anbernic RG28XX Controller,a:b4,b:b3,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b7,misc1:b1,rightshoulder:b8,leftstick:b12,rightstick:b13,start:b10,x:b5,y:b6,platform:Linux",
|
||||
"03000000190e00000110000010010000,Aquaplus Piece,a:b1,b:b0,back:b3,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b2,platform:Linux",
|
||||
"03000000790000003018000011010000,Arcade Fightstick F300,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux",
|
||||
"03000000a30c00002700000011010000,Astro City Mini,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux",
|
||||
@@ -1348,6 +1357,7 @@ const char *SDL_GAMECONTROLLER_DB[] = {
|
||||
"05000000ac0500002d0200001b010000,GameSir G4s,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b33,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux",
|
||||
"03000000ac0500007a05000011010000,GameSir G5,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b16,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux",
|
||||
"03000000373500009710000001020000,GameSir Kaleid Flux,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux",
|
||||
"03000000373500005810000001020000,GameSir K1,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux",
|
||||
"03000000ac0500001a06000011010000,GameSir T3 2.02,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux",
|
||||
"03000000373500000410000044010000,GameSir T4 Kaleid,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux",
|
||||
"03000000bc2000005656000011010000,GameSir T4w,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux",
|
||||
@@ -1446,6 +1456,7 @@ const char *SDL_GAMECONTROLLER_DB[] = {
|
||||
"03000000242f00008a00000011010000,JYS Adapter,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b3,platform:Linux",
|
||||
"03000000314100001935000000010000,LeadJoy Xeno Plus,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:+a5,rightx:a4,righty:a4,start:b7,x:b2,y:b3,platform:Linux",
|
||||
"030000006f0e00000103000000020000,Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux",
|
||||
"030000006f0e000001f5000010010000,Logic3 Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux",
|
||||
"030000006d040000d1ca000000000000,Logitech Chillstream,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux",
|
||||
"030000006d040000d1ca000011010000,Logitech Chillstream,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux",
|
||||
"030000006d04000016c2000010010000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux",
|
||||
@@ -1536,10 +1547,10 @@ const char *SDL_GAMECONTROLLER_DB[] = {
|
||||
"03000000853200000706000012010000,Nacon GC100,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux",
|
||||
"030000006b140000010c000010010000,Nacon GC400ES,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux",
|
||||
"05000000853200000503000000010000,Nacon MGX Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux",
|
||||
"0300000085320000170d000011010000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux",
|
||||
"0300000085320000190d000011010000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux",
|
||||
"0300000085320000180d000011010000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux",
|
||||
"0300000085320000160d000011010000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux",
|
||||
"0300000085320000170d000011010000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux",
|
||||
"0300000085320000180d000011010000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux",
|
||||
"0300000085320000190d000011010000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux",
|
||||
"030000000d0f00000900000010010000,Natec Genesis P44,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux",
|
||||
"030000004f1f00000800000011010000,NeoGeo PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux",
|
||||
"0300000092120000474e000000010000,NeoGeo X Arcade Stick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b3,y:b2,platform:Linux",
|
||||
@@ -1618,6 +1629,7 @@ const char *SDL_GAMECONTROLLER_DB[] = {
|
||||
"03000000d62000000520000050010000,PowerA Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux",
|
||||
"03000000d62000000b20000001010000,PowerA Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux",
|
||||
"03000000d62000000f20000001010000,PowerA Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b7,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux",
|
||||
"03000000d62000006520000002010000,PowerA Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux",
|
||||
"030000006d040000d2ca000011010000,Precision Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux",
|
||||
"03000000250900000017000010010000,PS SS N64 Adapter,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b5,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2~,righty:a3,start:b8,platform:Linux",
|
||||
"03000000ff1100004133000010010000,PS2 Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux",
|
||||
@@ -1751,7 +1763,8 @@ const char *SDL_GAMECONTROLLER_DB[] = {
|
||||
"030000005e0400008e02000073050000,Speedlink Torid,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux",
|
||||
"030000005e0400008e02000020200000,SpeedLink Xeox Pro Analog,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux",
|
||||
"03000000de280000ff11000001000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux",
|
||||
"05000000381000001214000001000000,SteelSeries Free,a:b0,b:b1,x:b3,y:b4,back:b10,guide:b12,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a2,righttrigger:a3,platform:Linux",
|
||||
"05000000381000001214000001000000,SteelSeries Free,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a3,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux",
|
||||
"05000000381000004114000000010000,SteelSeries Nimbus Cloud,a:b0,b:b1,x:b3,y:b4,back:b10,guide:b15,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,paddle1:b5,paddle2:b2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4,platform:Linux",
|
||||
"050000004e696d6275732b0000000000,SteelSeries Nimbus Plus,a:b0,b:b1,back:b10,guide:b11,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b12,x:b2,y:b3,platform:Linux",
|
||||
"03000000381000003014000075010000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux",
|
||||
"03000000381000003114000075010000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux",
|
||||
@@ -1797,9 +1810,10 @@ const char *SDL_GAMECONTROLLER_DB[] = {
|
||||
"03000000e00d00000300000003000000,TRBot Virtual Joypad,a:b11,b:b12,back:b15,dpdown:b6,dpleft:b3,dpright:b4,dpup:b5,leftshoulder:b17,leftstick:b21,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b22,righttrigger:a2,rightx:a3,righty:a4,start:b16,x:b13,y:b14,platform:Linux",
|
||||
"03000000f00600000300000003000000,TRBot Virtual Joypad,a:b11,b:b12,back:b15,dpdown:b6,dpleft:b3,dpright:b4,dpup:b5,leftshoulder:b17,leftstick:b21,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b22,righttrigger:a2,rightx:a3,righty:a4,start:b16,x:b13,y:b14,platform:Linux",
|
||||
"030000005f140000c501000010010000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux",
|
||||
"03000000f51000001370000000000000,Turtle Beach ReactR,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux",
|
||||
"03000000f51000001370000000010000,Turtle Beach ReactR,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux",
|
||||
"06000000f51000000870000003010000,Turtle Beach Recon,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux",
|
||||
"03000000f51000001370000000010000,Turtle Beach ReactR,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b8,start:b7,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux",
|
||||
"03000000f51000001370000000000000,Turtle Beach ReactR,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b8,start:b7,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux",
|
||||
"05000000f51000008f01000001000000,Turtle Beach Rematch Nintendo Switch Controller,a:b0,b:b1,x:b2,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,platform:Linux",
|
||||
"03000000100800000100000010010000,Twin PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux",
|
||||
"03000000c0160000e105000010010000,Ultimate Atari Fight Stick,a:b1,b:b2,back:b9,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b4,righttrigger:b5,start:b8,x:b0,y:b3,platform:Linux",
|
||||
"03000000151900005678000010010000,Uniplay U6,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux",
|
||||
@@ -2013,6 +2027,7 @@ const char *SDL_GAMECONTROLLER_DB[] = {
|
||||
"5553422c322d6178697320382d627574,iBuffalo Super Famicom Controller,a:b1,b:b0,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b17,rightshoulder:b18,start:b10,x:b3,y:b2,platform:Android",
|
||||
"64306137363261396266353433303531,InterAct GoPad,a:b24,b:b25,leftshoulder:b23,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,x:b21,y:b22,platform:Android",
|
||||
"532e542e442e20496e74657261637420,InterAct HammerHead FX,a:b23,b:b24,back:b30,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b26,leftstick:b22,lefttrigger:b28,leftx:a0,lefty:a1,rightshoulder:b27,rightstick:b25,righttrigger:b29,rightx:a2,righty:a3,start:b31,x:b20,y:b21,platform:Android",
|
||||
"05000000300f00001201000000780f00,Jess Tech Dual Analog Pad,a:b22,b:b23,back:b28,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b24,leftstick:b30,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b26,rightstick:b31,righttrigger:b27,rightx:a3,righty:a2,start:b29,x:b20,y:b21,platform:Android",
|
||||
"65346535636333663931613264643164,Joy-Con,a:b21,b:b22,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b23,y:b24,platform:Android",
|
||||
"33346566643039343630376565326335,Joy-Con (L),a:b0,b:b1,back:b7,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b17,x:b19,y:b2,platform:Android",
|
||||
"35313531613435623366313835326238,Joy-Con (L),a:b0,b:b1,back:b7,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b17,x:b19,y:b2,platform:Android",
|
||||
|
||||
@@ -2,8 +2,11 @@
|
||||
#define _AKGL_ACTOR_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include "types.h"
|
||||
#include "character.h"
|
||||
|
||||
#include <akstdlib.h>
|
||||
|
||||
#include <akgl/types.h>
|
||||
#include <akgl/character.h>
|
||||
|
||||
// ---- LOW WORD STATUSES ----
|
||||
|
||||
@@ -59,6 +62,7 @@ extern char *AKGL_ACTOR_STATE_STRING_NAMES[AKGL_ACTOR_MAX_STATES+1];
|
||||
#define AKGL_MAX_HEAP_ACTOR 64
|
||||
|
||||
typedef struct akgl_Actor {
|
||||
uint8_t type;
|
||||
uint8_t refcount;
|
||||
char name[AKGL_ACTOR_MAX_NAME_LENGTH];
|
||||
akgl_Character *basechar;
|
||||
@@ -70,21 +74,57 @@ typedef struct akgl_Actor {
|
||||
bool movement_controls_face;
|
||||
void *actorData;
|
||||
bool visible;
|
||||
bool simulating;
|
||||
SDL_Time movetimer;
|
||||
// Bounding box accounting for the actor's current real position plus physics delta
|
||||
SDL_FRect bbox;
|
||||
// Velocity. Combined effect of all forces acting on the actor resulting
|
||||
// in energy along an axis.
|
||||
float32_t vx;
|
||||
float32_t vy;
|
||||
float32_t vz;
|
||||
// Environmental velocity. These are the forces acting on the actor by the
|
||||
// environment (such as gravity and atmospheric drag)
|
||||
float32_t ex;
|
||||
float32_t ey;
|
||||
float32_t ez;
|
||||
// Thrust. Energy originating only from the actor's own acceleration on a
|
||||
// given axis, before the effects of gravity and drag.
|
||||
float32_t tx;
|
||||
float32_t ty;
|
||||
float32_t tz;
|
||||
// Acceleration. These are borrowed from the base character object.
|
||||
// A given axis resets to 0 when the actor stops moving in a given axis.
|
||||
float32_t ax;
|
||||
float32_t ay;
|
||||
float32_t az;
|
||||
// Max speed. These are borrowed from the base character object.
|
||||
float32_t sx;
|
||||
float32_t sy;
|
||||
float32_t sz;
|
||||
// Position.
|
||||
float32_t x;
|
||||
float32_t y;
|
||||
float32_t z;
|
||||
float32_t scale;
|
||||
// Reference to the BSP Node currently containing this actor
|
||||
aksl_TreeNode *bsphome;
|
||||
// Reference to the BSP linked list node currently holding this actor
|
||||
aksl_ListNode *bsplistnode;
|
||||
struct akgl_Actor *children[AKGL_ACTOR_MAX_CHILDREN];
|
||||
struct akgl_Actor *parent;
|
||||
|
||||
// method that controls logic update functions
|
||||
akerr_ErrorContext AKERR_NOIGNORE *(*updatefunc)(struct akgl_Actor *obj);
|
||||
// method that renders the actor to the currently active renderer
|
||||
akerr_ErrorContext AKERR_NOIGNORE *(*renderfunc)(struct akgl_Actor *obj);
|
||||
// method that changes the actor's face flags based on other state
|
||||
akerr_ErrorContext AKERR_NOIGNORE *(*facefunc)(struct akgl_Actor *obj);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *(*movementlogicfunc)(struct akgl_Actor *obj, SDL_Time curtimems);
|
||||
// method that performs movement logic on the actor based on state flags
|
||||
akerr_ErrorContext AKERR_NOIGNORE *(*movementlogicfunc)(struct akgl_Actor *obj, float32_t dt);
|
||||
// method that calculates the correct sprite frame for the actor's current state
|
||||
akerr_ErrorContext AKERR_NOIGNORE *(*changeframefunc)(struct akgl_Actor *obj, akgl_Sprite *curSprite, SDL_Time curtimems);
|
||||
// method to add a child to this actor
|
||||
akerr_ErrorContext AKERR_NOIGNORE *(*addchild)(struct akgl_Actor *obj, struct akgl_Actor *child);
|
||||
} akgl_Actor;
|
||||
|
||||
@@ -92,7 +132,7 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_actor_initialize(akgl_Actor *obj, char *
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_actor_set_character(akgl_Actor *obj, char *basecharname);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_actor_render(akgl_Actor *obj);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_actor_update(akgl_Actor *obj);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_actor_logic_movement(akgl_Actor *obj, SDL_Time curtimems);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_actor_logic_movement(akgl_Actor *obj, float32_t dt);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_actor_logic_changeframe(akgl_Actor *obj, akgl_Sprite *curSprite, SDL_Time curtimems);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_actor_automatic_face(akgl_Actor *obj);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_actor_add_child(akgl_Actor *obj, akgl_Actor *child);
|
||||
|
||||
@@ -12,7 +12,9 @@
|
||||
#define RESTORE_GCC_WARNINGS \
|
||||
_Pragma("GCC diagnostic pop")
|
||||
|
||||
#define AKGL_ERR_SDL AKERR_LAST_ERRNO_VALUE + 1
|
||||
#define AKGL_ERR_LOGICINTERRUPT AKERR_LAST_ERRNO_VALUE + 2
|
||||
#define AKGL_ERR_SDL AKERR_LAST_ERRNO_VALUE + 1 /** Error in the SDL library. See SDL_GetError() for more detail. */
|
||||
#define AKGL_ERR_LOGICINTERRUPT AKERR_LAST_ERRNO_VALUE + 2 /** Raised by an actor to tell the physics simulator not to process this node */
|
||||
#define AKGL_ERR_REGISTRY AKERR_LAST_ERRNO_VALUE + 3 /** The AKGL Registry was not able to fulfill the operation */
|
||||
#define AKGL_ERR_OOHEAP AKERR_LAST_ERRNO_VALUE + 4 /** The AKGL Heap in this context has been exhausted */
|
||||
|
||||
#endif // _ERROR_H_
|
||||
|
||||
@@ -3,10 +3,11 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <SDL3_mixer/SDL_mixer.h>
|
||||
#include "types.h"
|
||||
#include "tilemap.h"
|
||||
#include "renderer.h"
|
||||
#include "physics.h"
|
||||
#include <akgl/types.h>
|
||||
#include <akgl/tilemap.h>
|
||||
#include <akgl/renderer.h>
|
||||
#include <akgl/physics.h>
|
||||
#include <akgl/stage.h>
|
||||
|
||||
#define AKGL_VERSION "0.1.0"
|
||||
|
||||
@@ -44,14 +45,21 @@ typedef struct {
|
||||
} akgl_Game;
|
||||
|
||||
extern SDL_Window *window;
|
||||
extern akgl_Tilemap gamemap;
|
||||
extern MIX_Audio *bgm;
|
||||
extern MIX_Mixer *akgl_mixer;
|
||||
extern MIX_Track *akgl_tracks[AKGL_GAME_AUDIO_MAX_TRACKS];
|
||||
extern SDL_FRect camera;
|
||||
extern SDL_FRect _akgl_camera;
|
||||
extern akgl_Game game;
|
||||
extern akgl_RenderBackend renderer;
|
||||
extern akgl_PhysicsBackend physics;
|
||||
extern akgl_Stage _stage;
|
||||
extern akgl_RenderBackend _akgl_renderer;
|
||||
extern akgl_PhysicsBackend _akgl_physics;
|
||||
extern akgl_Tilemap _akgl_gamemap;
|
||||
|
||||
extern akgl_Stage *stage;
|
||||
extern akgl_Tilemap *gamemap;
|
||||
extern akgl_RenderBackend *renderer;
|
||||
extern akgl_PhysicsBackend *physics;
|
||||
extern SDL_FRect *camera;
|
||||
|
||||
#define AKGL_BITMASK_HAS(x, y) (x & y) == y
|
||||
#define AKGL_BITMASK_HASNOT(x, y) (x & y) != y
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
#ifndef _AKGL_HEAP_H_
|
||||
#define _AKGL_HEAP_H_
|
||||
|
||||
#include "sprite.h"
|
||||
#include "actor.h"
|
||||
#include "character.h"
|
||||
#include "staticstring.h"
|
||||
#include <akgl/sprite.h>
|
||||
#include <akgl/actor.h>
|
||||
#include <akgl/character.h>
|
||||
#include <akgl/staticstring.h>
|
||||
#include <akgl/stage.h>
|
||||
#include <akerror.h>
|
||||
#include <akstdlib.h>
|
||||
|
||||
#ifndef AKGL_MAX_HEAP_ACTOR
|
||||
#define AKGL_MAX_HEAP_ACTOR 64
|
||||
@@ -22,25 +24,43 @@
|
||||
#ifndef AKGL_MAX_HEAP_STRING
|
||||
#define AKGL_MAX_HEAP_STRING 256
|
||||
#endif
|
||||
#ifndef AKGL_MAX_HEAP_LIST
|
||||
#define AKGL_MAX_HEAP_LIST (AKGL_MAX_HEAP_ACTOR * 2) + 256
|
||||
#endif
|
||||
#ifndef AKGL_MAX_HEAP_TREE
|
||||
#define AKGL_MAX_HEAP_TREE 32
|
||||
#endif
|
||||
|
||||
extern akgl_Actor HEAP_ACTOR[AKGL_MAX_HEAP_ACTOR];
|
||||
extern akgl_Sprite HEAP_SPRITE[AKGL_MAX_HEAP_SPRITE];
|
||||
extern akgl_SpriteSheet HEAP_SPRITESHEET[AKGL_MAX_HEAP_SPRITESHEET];
|
||||
extern akgl_Character HEAP_CHARACTER[AKGL_MAX_HEAP_CHARACTER];
|
||||
extern akgl_String HEAP_STRING[AKGL_MAX_HEAP_STRING];
|
||||
extern aksl_ListNode HEAP_LIST[AKGL_MAX_HEAP_LIST];
|
||||
extern aksl_TreeNode HEAP_TREE[AKGL_MAX_HEAP_TREE];
|
||||
extern akgl_BSPLeaf HEAP_TREE_LEAVES[AKGL_MAX_HEAP_TREE];
|
||||
extern void *AKGL_LIST_SENTINEL;
|
||||
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_heap_init();
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_heap_init_list();
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_heap_init_tree();
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_heap_init_actor();
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_heap_next_actor(akgl_Actor **dest);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_heap_next_sprite(akgl_Sprite **dest);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_heap_next_spritesheet(akgl_SpriteSheet **dest);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_heap_next_character(akgl_Character **dest);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_heap_next_string(akgl_String **dest);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_heap_next_list(aksl_ListNode **dest);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_heap_next_tree(aksl_TreeNode **dest);
|
||||
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_heap_release_actor(akgl_Actor *ptr);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_heap_release_sprite(akgl_Sprite *ptr);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_heap_release_spritesheet(akgl_SpriteSheet *ptr);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_heap_release_character(akgl_Character *ptr);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_heap_release_string(akgl_String *ptr);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_heap_release_list(aksl_ListNode *ptr);
|
||||
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_heap_iter_list_release(aksl_ListNode *ptr, void *data);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_heap_iter_tree_release(aksl_TreeNode *ptr, void *data);
|
||||
|
||||
#endif //_AKGL_HEAP_H_
|
||||
|
||||
@@ -8,10 +8,13 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_object_value(json_t *obj, char
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_boolean_value(json_t *obj, char *key, bool *dest);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_integer_value(json_t *obj, char *key, int *dest);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_number_value(json_t *obj, char *key, float *dest);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_double_value(json_t *obj, char *key, double *dest);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_string_value(json_t *obj, char *key, akgl_String **dest);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_array_value(json_t *obj, char *key, json_t **dest);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_array_index_object(json_t *array, int index, json_t **dest);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_array_index_integer(json_t *array, int index, int *dest);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_array_index_string(json_t *array, int index, akgl_String **dest);
|
||||
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_with_default(akerr_ErrorContext *e, void *defval, void *dest, uint32_t defsize);
|
||||
|
||||
#endif // _JSON_HELPERS_H_
|
||||
|
||||
@@ -5,12 +5,13 @@
|
||||
#include <akerror.h>
|
||||
#include <akgl/actor.h>
|
||||
#include <akgl/iterator.h>
|
||||
#include <akgl/staticstring.h>
|
||||
|
||||
typedef struct akgl_PhysicsBackend {
|
||||
akerr_ErrorContext AKERR_NOIGNORE *(*simulate)(struct akgl_PhysicsBackend *self, akgl_Iterator *opflags);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *(*gravity)(struct akgl_PhysicsBackend *self, akgl_Actor *actor, SDL_Time curtime);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *(*gravity)(struct akgl_PhysicsBackend *self, akgl_Actor *actor, float32_t dt);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *(*collide)(struct akgl_PhysicsBackend *self, akgl_Actor *a1, akgl_Actor *a2);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *(*move)(struct akgl_PhysicsBackend *self, akgl_Actor *actor, SDL_Time curtime);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *(*move)(struct akgl_PhysicsBackend *self, akgl_Actor *actor, float32_t dt);
|
||||
|
||||
double drag_x;
|
||||
double drag_y;
|
||||
@@ -19,21 +20,21 @@ typedef struct akgl_PhysicsBackend {
|
||||
double gravity_y;
|
||||
double gravity_z;
|
||||
SDL_Time gravity_time;
|
||||
SDL_Time timer_gravity;
|
||||
|
||||
SDL_Time timer_gravity;
|
||||
} akgl_PhysicsBackend;
|
||||
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_null_gravity(akgl_PhysicsBackend *self, akgl_Actor *actor, SDL_Time curtime);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_null_gravity(akgl_PhysicsBackend *self, akgl_Actor *actor, float32_t dt);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_null_collide(akgl_PhysicsBackend *self, akgl_Actor *a1, akgl_Actor *a2);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_null_move(akgl_PhysicsBackend *self, akgl_Actor *actor, SDL_Time curtime);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_null_move(akgl_PhysicsBackend *self, akgl_Actor *actor, float32_t dt);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_init_null(akgl_PhysicsBackend *self);
|
||||
|
||||
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_ss_gravity(akgl_PhysicsBackend *self, akgl_Actor *actor, SDL_Time curtime);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_ss_collide(akgl_PhysicsBackend *self, akgl_Actor *a1, akgl_Actor *a2);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_ss_move(akgl_PhysicsBackend *self, akgl_Actor *actor, SDL_Time curtime);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_init_sidescroller(akgl_PhysicsBackend *self);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_arcade_gravity(akgl_PhysicsBackend *self, akgl_Actor *actor, float32_t dt);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_arcade_collide(akgl_PhysicsBackend *self, akgl_Actor *a1, akgl_Actor *a2);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_arcade_move(akgl_PhysicsBackend *self, akgl_Actor *actor, float32_t dt);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_init_arcade(akgl_PhysicsBackend *self);
|
||||
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_factory(akgl_PhysicsBackend *self, akgl_String *type);
|
||||
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_simulate(akgl_PhysicsBackend *self, akgl_Iterator *opflags);
|
||||
|
||||
|
||||
45
include/akgl/stage.h
Normal file
45
include/akgl/stage.h
Normal file
@@ -0,0 +1,45 @@
|
||||
#ifndef _STAGE_H_
|
||||
#define _STAGE_H_
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
#include <akstdlib.h>
|
||||
|
||||
#include <akgl/actor.h>
|
||||
|
||||
#define AKGL_STAGE_PARTITION_HORIZONTAL 0
|
||||
#define AKGL_STAGE_PARTITION_VERTICAL 1
|
||||
#define AKGL_STAGE_PARTITION_MAXDEPTH 4
|
||||
|
||||
typedef struct akgl_BSPContext {
|
||||
aksl_TreeNode *left;
|
||||
aksl_TreeNode *right;
|
||||
aksl_TreeNode *parent;
|
||||
} akgl_BSPContext;
|
||||
|
||||
typedef struct akgl_BSPLeaf {
|
||||
SDL_FRect extent;
|
||||
aksl_ListNode *actors;
|
||||
} akgl_BSPLeaf;
|
||||
|
||||
// Stages are collections of lights and cameras in a 2D or 3D space wherein actors
|
||||
// and backgrounds are placed and directed for action.
|
||||
typedef struct akgl_Stage {
|
||||
aksl_TreeNode bsp;
|
||||
akgl_BSPLeaf _rootleaf;
|
||||
akerr_ErrorContext AKERR_NOIGNORE *(*partition)(struct akgl_Stage *self);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *(*partition_actor)(struct akgl_Stage *self, akgl_Actor *actor);
|
||||
} akgl_Stage;
|
||||
|
||||
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_stage_2d(akgl_Stage *self);
|
||||
|
||||
// A function to divide the stage into a binary space partition tree with lists of actors in each partition
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_stage_2d_partition(akgl_Stage *self);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_stage_2d_partition_switchdirection(uint8_t direction, uint8_t *dest);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_stage_2d_bsp_actoriter(aksl_ListNode *node, void *data);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_stage_2d_bsp(aksl_TreeNode *root, aksl_ListNode *actors, SDL_FRect extents, uint8_t direction, uint8_t depth, uint8_t maxdepth);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_stage_2d_bspfree(akgl_Stage *self);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_stage_2d_partition(akgl_Stage *self);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_stage_2d_bsp_move(akgl_Stage *self, akgl_Actor *actor);
|
||||
|
||||
#endif // _STAGE_H_
|
||||
@@ -10,9 +10,9 @@
|
||||
typedef struct
|
||||
{
|
||||
int refcount;
|
||||
int length;
|
||||
char data[AKGL_MAX_STRING_LENGTH];
|
||||
} akgl_String;
|
||||
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_string_initialize(akgl_String *obj, char *init);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_string_copy(akgl_String *src, akgl_String *dst, int count);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_string_initialize(akgl_String *obj, char *init);akerr_ErrorContext AKERR_NOIGNORE *akgl_string_copy(akgl_String *src, akgl_String *dst, int count);
|
||||
#endif //_STRING_H_
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
#define _TILEMAP_H_
|
||||
|
||||
#include <limits.h>
|
||||
#include "actor.h"
|
||||
#include "staticstring.h"
|
||||
#include <akgl/actor.h>
|
||||
#include <akgl/staticstring.h>
|
||||
#include <akgl/physics.h>
|
||||
#include <jansson.h>
|
||||
|
||||
#define AKGL_TILEMAP_MAX_WIDTH 512
|
||||
@@ -98,6 +99,10 @@ typedef struct {
|
||||
float p_rate;
|
||||
akgl_Tileset tilesets[AKGL_TILEMAP_MAX_TILESETS];
|
||||
akgl_TilemapLayer layers[AKGL_TILEMAP_MAX_LAYERS];
|
||||
|
||||
// Different levels may have different physics.
|
||||
bool use_own_physics;
|
||||
akgl_PhysicsBackend physics;
|
||||
} akgl_Tilemap;
|
||||
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_tilemap_load(char *fname, akgl_Tilemap *dest);
|
||||
|
||||
65
src/actor.c
65
src/actor.c
@@ -1,7 +1,9 @@
|
||||
#include <SDL3/SDL.h>
|
||||
#include <SDL3_image/SDL_image.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <akerror.h>
|
||||
#include <akstdlib.h>
|
||||
|
||||
#include <akgl/physics.h>
|
||||
#include <akgl/game.h>
|
||||
@@ -51,6 +53,10 @@ akerr_ErrorContext *akgl_actor_set_character(akgl_Actor *obj, char *basecharname
|
||||
obj->basechar = SDL_GetPointerProperty(AKGL_REGISTRY_CHARACTER, basecharname, NULL);
|
||||
|
||||
FAIL_ZERO_RETURN(errctx, obj->basechar, AKERR_NULLPOINTER, "Character not found in the registry");
|
||||
obj->ax = 0;
|
||||
obj->ay = 0;
|
||||
obj->sx = obj->basechar->sx;
|
||||
obj->sy = obj->basechar->sy;
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
|
||||
@@ -113,20 +119,25 @@ akerr_ErrorContext *akgl_actor_logic_changeframe(akgl_Actor *obj, akgl_Sprite *c
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
|
||||
// raises AKGL_ERR_LOGICINTERRUPT if we don't want the physics object to process us
|
||||
akerr_ErrorContext *akgl_actor_logic_movement(akgl_Actor *obj, SDL_Time curtime)
|
||||
// raises AKGL_ERR_LOGICINTERRUPT if we don't want the physics simulator to process us
|
||||
akerr_ErrorContext *akgl_actor_logic_movement(akgl_Actor *actor, float32_t dt)
|
||||
{
|
||||
PREPARE_ERROR(errctx);
|
||||
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "obj");
|
||||
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "obj->basechar");
|
||||
if ( obj->vx > obj->basechar->sx ) {
|
||||
obj->vx = obj->basechar->sx;
|
||||
FAIL_ZERO_RETURN(errctx, actor, AKERR_NULLPOINTER, "actor");
|
||||
FAIL_ZERO_RETURN(errctx, actor, AKERR_NULLPOINTER, "actor->basechar");
|
||||
actor->sx = actor->basechar->sx;
|
||||
actor->sy = actor->basechar->sy;
|
||||
actor->sz = actor->basechar->sz;
|
||||
if ( AKGL_BITMASK_HAS(actor->state, AKGL_ACTOR_STATE_MOVING_LEFT) ) {
|
||||
actor->ax = -actor->basechar->ax;
|
||||
} else if ( AKGL_BITMASK_HAS(actor->state, AKGL_ACTOR_STATE_MOVING_RIGHT) ) {
|
||||
actor->ax = actor->basechar->ax;
|
||||
}
|
||||
if ( obj->vy > obj->basechar->sy ) {
|
||||
obj->vy = obj->basechar->sy;
|
||||
if ( AKGL_BITMASK_HAS(actor->state, AKGL_ACTOR_STATE_MOVING_UP) ) {
|
||||
actor->ay = -actor->basechar->ay;
|
||||
} else if ( AKGL_BITMASK_HAS(actor->state, AKGL_ACTOR_STATE_MOVING_DOWN) ) {
|
||||
actor->ay = actor->basechar->ay;
|
||||
}
|
||||
// Effectively a NOOP, this is handled by the physics engine now
|
||||
// These functions are still present in case the library user wants per-actor behavior
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
|
||||
@@ -201,7 +212,7 @@ akerr_ErrorContext *akgl_actor_render(akgl_Actor *obj)
|
||||
|
||||
ATTEMPT {
|
||||
CATCH(errctx, akgl_character_sprite_get(obj->basechar, obj->state, &curSprite));
|
||||
CATCH(errctx, actor_visible(obj, &camera, &visible));
|
||||
CATCH(errctx, actor_visible(obj, camera, &visible));
|
||||
} CLEANUP {
|
||||
} PROCESS(errctx) {
|
||||
} HANDLE(errctx, AKERR_KEY) {
|
||||
@@ -233,16 +244,16 @@ akerr_ErrorContext *akgl_actor_render(akgl_Actor *obj)
|
||||
} FINISH(errctx, true);
|
||||
|
||||
if ( obj->parent != NULL ) {
|
||||
dest.x = (obj->parent->x + obj->x - camera.x);
|
||||
dest.y = (obj->parent->y + obj->y - camera.y);
|
||||
dest.x = (obj->parent->x + obj->x - camera->x);
|
||||
dest.y = (obj->parent->y + obj->y - camera->y);
|
||||
} else {
|
||||
dest.x = (obj->x - camera.x);
|
||||
dest.y = (obj->y - camera.y);
|
||||
dest.x = (obj->x - camera->x);
|
||||
dest.y = (obj->y - camera->y);
|
||||
}
|
||||
dest.w = curSprite->width * obj->scale;
|
||||
dest.h = curSprite->width * obj->scale;
|
||||
|
||||
PASS(errctx, renderer.draw_texture(&renderer, curSprite->sheet->texture, &src, &dest, 0, NULL, SDL_FLIP_NONE));
|
||||
PASS(errctx, renderer->draw_texture(renderer, curSprite->sheet->texture, &src, &dest, 0, NULL, SDL_FLIP_NONE));
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
|
||||
@@ -268,10 +279,12 @@ akerr_ErrorContext *akgl_actor_add_child(akgl_Actor *obj, akgl_Actor *child)
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_Actor_cmhf_left_on(akgl_Actor *obj, SDL_Event *event)
|
||||
{
|
||||
PREPARE_ERROR(errctx);
|
||||
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "NULL actor");
|
||||
FAIL_ZERO_RETURN(errctx, event, AKERR_NULLPOINTER, "NULL event");
|
||||
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "actor");
|
||||
FAIL_ZERO_RETURN(errctx, event, AKERR_NULLPOINTER, "event");
|
||||
FAIL_ZERO_RETURN(errctx, obj->basechar, AKERR_NULLPOINTER, "actor->basechar");
|
||||
//SDL_Log("event %d (button %d / key %d) moves actor left", event->type, event->gbutton.which, event->key.key);
|
||||
AKGL_BITMASK_DEL(obj->state, (AKGL_ACTOR_STATE_FACE_ALL | AKGL_ACTOR_STATE_MOVING_ALL));
|
||||
obj->ax = -(obj->basechar->ax);
|
||||
AKGL_BITMASK_ADD(obj->state, (AKGL_ACTOR_STATE_MOVING_LEFT | AKGL_ACTOR_STATE_FACE_LEFT));
|
||||
//SDL_Log("new target actor state: %b", obj->state);
|
||||
SUCCEED_RETURN(errctx);
|
||||
@@ -283,6 +296,9 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_Actor_cmhf_left_off(akgl_Actor *obj, SDL
|
||||
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "NULL actor");
|
||||
FAIL_ZERO_RETURN(errctx, event, AKERR_NULLPOINTER, "NULL event");
|
||||
//SDL_Log("event %d (button %d / key %d) stops moving actor left", event->type, event->gbutton.which, event->key.key);
|
||||
obj->ax = 0;
|
||||
obj->ex = 0;
|
||||
obj->tx = 0;
|
||||
obj->vx = 0;
|
||||
AKGL_BITMASK_DEL(obj->state, AKGL_ACTOR_STATE_MOVING_LEFT);
|
||||
//SDL_Log("new target actor state: %b", obj->state);
|
||||
@@ -294,7 +310,9 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_Actor_cmhf_right_on(akgl_Actor *obj, SDL
|
||||
PREPARE_ERROR(errctx);
|
||||
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "NULL actor");
|
||||
FAIL_ZERO_RETURN(errctx, event, AKERR_NULLPOINTER, "NULL event");
|
||||
FAIL_ZERO_RETURN(errctx, obj->basechar, AKERR_NULLPOINTER, "actor->basechar");
|
||||
//SDL_Log("event %d (button %d / key %d) moves actor right", event->type, event->gbutton.which, event->key.key);
|
||||
obj->ax = obj->basechar->ax;
|
||||
AKGL_BITMASK_DEL(obj->state, (AKGL_ACTOR_STATE_FACE_ALL | AKGL_ACTOR_STATE_MOVING_ALL));
|
||||
AKGL_BITMASK_ADD(obj->state, (AKGL_ACTOR_STATE_MOVING_RIGHT | AKGL_ACTOR_STATE_FACE_RIGHT));
|
||||
//SDL_Log("new target actor state: %b", obj->state);
|
||||
@@ -307,6 +325,9 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_Actor_cmhf_right_off(akgl_Actor *obj, SD
|
||||
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "NULL actor");
|
||||
FAIL_ZERO_RETURN(errctx, event, AKERR_NULLPOINTER, "NULL event");
|
||||
//SDL_Log("event %d (button %d / key %d) stops moving actor right", event->type, event->gbutton.which, event->key.key);
|
||||
obj->ax = 0;
|
||||
obj->ex = 0;
|
||||
obj->tx = 0;
|
||||
obj->vx = 0;
|
||||
AKGL_BITMASK_DEL(obj->state, AKGL_ACTOR_STATE_MOVING_RIGHT);
|
||||
//SDL_Log("new target actor state: %b", obj->state);
|
||||
@@ -319,6 +340,7 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_Actor_cmhf_up_on(akgl_Actor *obj, SDL_Ev
|
||||
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "NULL actor");
|
||||
FAIL_ZERO_RETURN(errctx, event, AKERR_NULLPOINTER, "NULL event");
|
||||
//SDL_Log("event %d (button %d / key %d) moves actor up", event->type, event->gbutton.which, event->key.key);
|
||||
obj->ay = -(obj->basechar->ay);
|
||||
AKGL_BITMASK_DEL(obj->state, (AKGL_ACTOR_STATE_FACE_ALL | AKGL_ACTOR_STATE_MOVING_ALL));
|
||||
AKGL_BITMASK_ADD(obj->state, (AKGL_ACTOR_STATE_FACE_UP | AKGL_ACTOR_STATE_MOVING_UP));
|
||||
//SDL_Log("new target actor state: %b", obj->state);
|
||||
@@ -331,6 +353,9 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_Actor_cmhf_up_off(akgl_Actor *obj, SDL_E
|
||||
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "NULL actor");
|
||||
FAIL_ZERO_RETURN(errctx, event, AKERR_NULLPOINTER, "NULL event");
|
||||
//SDL_Log("event %d (button %d / key %d) stops moving actor up", event->type, event->gbutton.which, event->key.key);
|
||||
obj->ay = 0;
|
||||
obj->ey = 0;
|
||||
obj->ty = 0;
|
||||
obj->vy = 0;
|
||||
AKGL_BITMASK_DEL(obj->state, AKGL_ACTOR_STATE_MOVING_UP);
|
||||
//SDL_Log("new target actor state: %b", obj->state);
|
||||
@@ -343,6 +368,7 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_Actor_cmhf_down_on(akgl_Actor *obj, SDL_
|
||||
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "NULL actor");
|
||||
FAIL_ZERO_RETURN(errctx, event, AKERR_NULLPOINTER, "NULL event");
|
||||
//SDL_Log("event %d (button %d / key %d) moves actor down", event->type, event->gbutton.which, event->key.key);
|
||||
obj->ay = obj->basechar->ay;
|
||||
AKGL_BITMASK_DEL(obj->state, (AKGL_ACTOR_STATE_FACE_ALL | AKGL_ACTOR_STATE_MOVING_ALL));
|
||||
AKGL_BITMASK_ADD(obj->state, (AKGL_ACTOR_STATE_MOVING_DOWN | AKGL_ACTOR_STATE_FACE_DOWN));
|
||||
//SDL_Log("new target actor state: %b", obj->state);
|
||||
@@ -355,6 +381,9 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_Actor_cmhf_down_off(akgl_Actor *obj, SDL
|
||||
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "NULL actor");
|
||||
FAIL_ZERO_RETURN(errctx, event, AKERR_NULLPOINTER, "NULL event");
|
||||
//SDL_Log("event %d (button %d / key %d) stops moving actor down", event->type, event->gbutton.which, event->key.key);
|
||||
obj->ty = 0;
|
||||
obj->ey = 0;
|
||||
obj->ay = 0;
|
||||
obj->vy = 0;
|
||||
AKGL_BITMASK_DEL(obj->state, AKGL_ACTOR_STATE_MOVING_DOWN);
|
||||
//SDL_Log("new target actor state: %b", obj->state);
|
||||
|
||||
@@ -277,7 +277,7 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_controller_default(int controlmapid, cha
|
||||
controlmap->jsid = jsid;
|
||||
|
||||
controlmap->target = SDL_GetPointerProperty(AKGL_REGISTRY_ACTOR, actorname, NULL);
|
||||
FAIL_ZERO_BREAK(errctx, controlmap->target, AKERR_REGISTRY, "Actor %s not found in registry", actorname);
|
||||
FAIL_ZERO_BREAK(errctx, controlmap->target, AKGL_ERR_REGISTRY, "Actor %s not found in registry", actorname);
|
||||
|
||||
// ---- KEYBOARD CONTROLS ----
|
||||
|
||||
|
||||
@@ -20,11 +20,11 @@ void akgl_draw_background(int w, int h)
|
||||
for (x = 0; x < w; x += dx) {
|
||||
/* use an 8x8 checkerboard pattern */
|
||||
i = (((x ^ y) >> 3) & 1);
|
||||
SDL_SetRenderDrawColor(renderer.sdl_renderer, col[i].r, col[i].g, col[i].b, col[i].a);
|
||||
SDL_SetRenderDrawColor(renderer->sdl_renderer, col[i].r, col[i].g, col[i].b, col[i].a);
|
||||
|
||||
rect.x = (float)x;
|
||||
rect.y = (float)y;
|
||||
SDL_RenderFillRect(renderer.sdl_renderer, &rect);
|
||||
SDL_RenderFillRect(renderer->sdl_renderer, &rect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
88
src/game.c
88
src/game.c
@@ -19,17 +19,24 @@
|
||||
#include <akgl/SDL_GameControllerDB.h>
|
||||
|
||||
SDL_Window *window = NULL;
|
||||
akgl_RenderBackend renderer;
|
||||
akgl_PhysicsBackend physics;
|
||||
akgl_Frame ball;
|
||||
akgl_Frame paddle1;
|
||||
akgl_Frame paddle2;
|
||||
akgl_Frame table;
|
||||
akgl_Tilemap gamemap;
|
||||
|
||||
// Currently active objects
|
||||
akgl_RenderBackend *renderer;
|
||||
akgl_PhysicsBackend *physics;
|
||||
SDL_FRect *camera;
|
||||
akgl_Tilemap *gamemap;
|
||||
akgl_Stage *stage;
|
||||
|
||||
// Default objects
|
||||
akgl_RenderBackend _akgl_renderer;
|
||||
akgl_PhysicsBackend _akgl_physics;
|
||||
SDL_FRect _akgl_camera;
|
||||
akgl_Tilemap _akgl_gamemap;
|
||||
akgl_Stage _akgl_stage;
|
||||
|
||||
MIX_Audio *bgm = NULL;
|
||||
MIX_Mixer *akgl_mixer = NULL;
|
||||
MIX_Track *akgl_tracks[AKGL_GAME_AUDIO_MAX_TRACKS];
|
||||
SDL_FRect camera;
|
||||
akgl_Game game;
|
||||
|
||||
void akgl_game_lowfps(void)
|
||||
@@ -45,31 +52,32 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_game_init()
|
||||
|
||||
int i = 0;
|
||||
PREPARE_ERROR(e);
|
||||
ATTEMPT {
|
||||
strncpy((char *)&game.libversion, AKGL_VERSION, 32);
|
||||
game.gameStartTime = SDL_GetTicksNS();
|
||||
game.lastIterTime = game.gameStartTime;
|
||||
game.lastFPSTime = game.gameStartTime;
|
||||
game.lowfpsfunc = &akgl_game_lowfps;
|
||||
game.statelock = SDL_CreateMutex();
|
||||
FAIL_ZERO_RETURN(e, game.statelock, AKGL_ERR_SDL, "%s", SDL_GetError());
|
||||
CATCH(e, akgl_game_state_lock());
|
||||
FAIL_ZERO_BREAK(e, strlen((char *)&game.name), AKERR_NULLPOINTER, "Must provide game name");
|
||||
FAIL_ZERO_BREAK(e, strlen((char *)&game.version), AKERR_NULLPOINTER, "Must provide game version");
|
||||
FAIL_ZERO_BREAK(e, strlen((char *)&game.uri), AKERR_NULLPOINTER, "Must provide game uri");
|
||||
CATCH(e, akgl_heap_init());
|
||||
CATCH(e, akgl_registry_init_actor());
|
||||
CATCH(e, akgl_registry_init_sprite());
|
||||
CATCH(e, akgl_registry_init_spritesheet());
|
||||
CATCH(e, akgl_registry_init_character());
|
||||
CATCH(e, akgl_registry_init_font());
|
||||
CATCH(e, akgl_registry_init_music());
|
||||
CATCH(e, akgl_registry_init_properties());
|
||||
CATCH(e, akgl_registry_init_actor_state_strings());
|
||||
} CLEANUP {
|
||||
//IGNORE(akgl_game_state_unlock());
|
||||
} PROCESS(e) {
|
||||
} FINISH(e, true)
|
||||
|
||||
akerr_name_for_status(AKGL_ERR_SDL, "SDL Error");
|
||||
akerr_name_for_status(AKGL_ERR_LOGICINTERRUPT, "AKGL Logic Interrupt");
|
||||
akerr_name_for_status(AKGL_ERR_REGISTRY, "AKGL Registry Error");
|
||||
akerr_name_for_status(AKGL_ERR_OOHEAP, "AKGL Heap Capacity");
|
||||
|
||||
strncpy((char *)&game.libversion, AKGL_VERSION, 32);
|
||||
game.gameStartTime = SDL_GetTicksNS();
|
||||
game.lastIterTime = game.gameStartTime;
|
||||
game.lastFPSTime = game.gameStartTime;
|
||||
game.lowfpsfunc = &akgl_game_lowfps;
|
||||
game.statelock = SDL_CreateMutex();
|
||||
FAIL_ZERO_RETURN(e, game.statelock, AKGL_ERR_SDL, "%s", SDL_GetError());
|
||||
PASS(e, akgl_game_state_lock());
|
||||
FAIL_ZERO_RETURN(e, strlen((char *)&game.name), AKERR_NULLPOINTER, "Must provide game name");
|
||||
FAIL_ZERO_RETURN(e, strlen((char *)&game.version), AKERR_NULLPOINTER, "Must provide game version");
|
||||
FAIL_ZERO_RETURN(e, strlen((char *)&game.uri), AKERR_NULLPOINTER, "Must provide game uri");
|
||||
PASS(e, akgl_heap_init());
|
||||
PASS(e, akgl_registry_init_actor());
|
||||
PASS(e, akgl_registry_init_sprite());
|
||||
PASS(e, akgl_registry_init_spritesheet());
|
||||
PASS(e, akgl_registry_init_character());
|
||||
PASS(e, akgl_registry_init_font());
|
||||
PASS(e, akgl_registry_init_music());
|
||||
PASS(e, akgl_registry_init_properties());
|
||||
PASS(e, akgl_registry_init_actor_state_strings());
|
||||
|
||||
SDL_SetAppMetadata(game.name, game.version, game.uri);
|
||||
|
||||
@@ -113,6 +121,13 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_game_init()
|
||||
AKGL_ERR_SDL,
|
||||
"Couldn't initialize front engine: %s",
|
||||
SDL_GetError());
|
||||
|
||||
camera = &_akgl_camera;
|
||||
renderer = &_akgl_renderer;
|
||||
physics = &_akgl_physics;
|
||||
gamemap = &_akgl_gamemap;
|
||||
stage = &_akgl_stage;
|
||||
|
||||
PASS(e, akgl_game_state_unlock());
|
||||
SUCCEED_RETURN(e);
|
||||
}
|
||||
@@ -432,15 +447,16 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_game_update(akgl_Iterator *opflags)
|
||||
continue;
|
||||
}
|
||||
if ( AKGL_BITMASK_HAS(opflags->flags, AKGL_ITERATOR_OP_TILEMAPSCALE) ) {
|
||||
PASS(e, akgl_tilemap_scale_actor(&gamemap, actor));
|
||||
PASS(e, akgl_tilemap_scale_actor(gamemap, actor));
|
||||
} else {
|
||||
actor->scale = 1.0;
|
||||
}
|
||||
PASS(e, actor->updatefunc(actor));
|
||||
}
|
||||
}
|
||||
PASS(e, physics.simulate(&physics, NULL));
|
||||
PASS(e, renderer.draw_world(&renderer, NULL));
|
||||
|
||||
PASS(e, physics->simulate(physics, NULL));
|
||||
PASS(e, renderer->draw_world(renderer, NULL));
|
||||
PASS(e, akgl_game_state_unlock());
|
||||
SUCCEED_RETURN(e);
|
||||
}
|
||||
|
||||
261
src/heap.c
261
src/heap.c
@@ -1,3 +1,5 @@
|
||||
/** @file */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <akerror.h>
|
||||
|
||||
@@ -8,12 +10,18 @@
|
||||
#include <akgl/staticstring.h>
|
||||
#include <akgl/iterator.h>
|
||||
#include <akgl/error.h>
|
||||
#include <akgl/stage.h>
|
||||
|
||||
akgl_Actor HEAP_ACTOR[AKGL_MAX_HEAP_ACTOR];
|
||||
akgl_Sprite HEAP_SPRITE[AKGL_MAX_HEAP_SPRITE];
|
||||
akgl_SpriteSheet HEAP_SPRITESHEET[AKGL_MAX_HEAP_SPRITESHEET];
|
||||
akgl_Character HEAP_CHARACTER[AKGL_MAX_HEAP_CHARACTER];
|
||||
akgl_String HEAP_STRING[AKGL_MAX_HEAP_STRING];
|
||||
aksl_ListNode HEAP_LIST[AKGL_MAX_HEAP_LIST];
|
||||
aksl_TreeNode HEAP_TREE[AKGL_MAX_HEAP_TREE];
|
||||
akgl_BSPLeaf HEAP_TREE_LEAVES[AKGL_MAX_HEAP_TREE];
|
||||
|
||||
void *AKGL_LIST_SENTINEL = (void *)1; /** Sentinel value used for aksl_ListNode objects to determine if they are available */
|
||||
|
||||
akerr_ErrorContext *akgl_heap_init()
|
||||
{
|
||||
@@ -21,6 +29,8 @@ akerr_ErrorContext *akgl_heap_init()
|
||||
int i = 0;
|
||||
akerr_name_for_status(AKGL_ERR_SDL, "SDL Error");
|
||||
PASS(errctx, akgl_heap_init_actor());
|
||||
PASS(errctx, akgl_heap_init_list());
|
||||
PASS(errctx, akgl_heap_init_tree());
|
||||
for ( i = 0; i < AKGL_MAX_HEAP_SPRITE; i++) {
|
||||
memset(&HEAP_SPRITE[i], 0x00, sizeof(akgl_Sprite));
|
||||
}
|
||||
@@ -36,6 +46,27 @@ akerr_ErrorContext *akgl_heap_init()
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
|
||||
akerr_ErrorContext *akgl_heap_init_list(void)
|
||||
{
|
||||
PREPARE_ERROR(e);
|
||||
for ( int i = 0; i < AKGL_MAX_HEAP_LIST; i++) {
|
||||
memset(&HEAP_LIST[i], 0x00, sizeof(aksl_ListNode));
|
||||
HEAP_LIST[i].data = AKGL_LIST_SENTINEL;
|
||||
}
|
||||
SUCCEED_RETURN(e);
|
||||
}
|
||||
|
||||
akerr_ErrorContext *akgl_heap_init_tree(void)
|
||||
{
|
||||
PREPARE_ERROR(e);
|
||||
for ( int i = 0; i < AKGL_MAX_HEAP_TREE; i++) {
|
||||
memset(&HEAP_TREE[i], 0x00, sizeof(aksl_TreeNode));
|
||||
HEAP_TREE[i].leaf = AKGL_LIST_SENTINEL;
|
||||
memset(&HEAP_TREE_LEAVES[i], 0x00, sizeof(akgl_BSPLeaf));
|
||||
}
|
||||
SUCCEED_RETURN(e);
|
||||
}
|
||||
|
||||
akerr_ErrorContext *akgl_heap_init_actor(void)
|
||||
{
|
||||
PREPARE_ERROR(e);
|
||||
@@ -45,6 +76,143 @@ akerr_ErrorContext *akgl_heap_init_actor(void)
|
||||
SUCCEED_RETURN(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the next aksl_ListNode from the heap
|
||||
*
|
||||
* @param[out] dest The pointer that will hold the procured aksl_ListNode
|
||||
*
|
||||
* @throws AKGL_ERR_OOHEAP There are no available nodes in HEAP_LIST
|
||||
* @return akerr_ErrorContext*
|
||||
*/
|
||||
|
||||
akerr_ErrorContext *akgl_heap_next_list(aksl_ListNode **dest)
|
||||
{
|
||||
PREPARE_ERROR(errctx);
|
||||
for (int i = 0; i < AKGL_MAX_HEAP_LIST; i++ ) {
|
||||
if ( HEAP_LIST[i].data != AKGL_LIST_SENTINEL ) {
|
||||
continue;
|
||||
}
|
||||
*dest = &HEAP_LIST[i];
|
||||
HEAP_LIST[i].data = NULL;
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
FAIL_RETURN(errctx, AKGL_ERR_OOHEAP, "Unable to find unused list on the heap");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the next aksl_TreeNode from the heap
|
||||
*
|
||||
* @param[out] dest The pointer that will hold the procured tree node
|
||||
*
|
||||
* @throws AKGL_ERR_OOHEAP There are no available nodes in HEAP_TREE
|
||||
* @return akerr_ErrorContext*
|
||||
*/
|
||||
|
||||
akerr_ErrorContext *akgl_heap_next_tree(aksl_TreeNode **dest)
|
||||
{
|
||||
PREPARE_ERROR(errctx);
|
||||
for (int i = 0; i < AKGL_MAX_HEAP_TREE; i++ ) {
|
||||
if ( HEAP_TREE[i].leaf != AKGL_LIST_SENTINEL ) {
|
||||
continue;
|
||||
}
|
||||
*dest = &HEAP_TREE[i];
|
||||
HEAP_TREE[i].leaf = &HEAP_TREE_LEAVES[i];
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
FAIL_RETURN(errctx, AKGL_ERR_OOHEAP, "Unable to find unused tree on the heap");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Release an aksl_ListNode that came from HEAP_TREE to make it available again
|
||||
*
|
||||
* @param[in] tree The aksl_ListNode to release.
|
||||
*
|
||||
* @return akerr_ErrorContext*
|
||||
*/
|
||||
|
||||
akerr_ErrorContext *akgl_heap_release_list(aksl_ListNode *list)
|
||||
{
|
||||
PREPARE_ERROR(e);
|
||||
FAIL_ZERO_RETURN(e, list, AKERR_NULLPOINTER, "list");
|
||||
list->next = NULL;
|
||||
list->prev = NULL;
|
||||
list->data = (void *)AKGL_LIST_SENTINEL;
|
||||
SUCCEED_RETURN(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Release an aksl_TreeNode that came from HEAP_TREE to make it available again
|
||||
*
|
||||
* @param[in] tree The aksl_TreeNode to release. Ensure the leaf on this node has been released and the leaf is set to NULL.
|
||||
*
|
||||
* @throws AKERR_VALUE The aksl_TreeNode contains a leaf that has not been released.
|
||||
* @return akerr_ErrorContext*
|
||||
*/
|
||||
|
||||
akerr_ErrorContext *akgl_heap_release_tree(aksl_TreeNode *tree)
|
||||
{
|
||||
PREPARE_ERROR(e);
|
||||
FAIL_ZERO_RETURN(e, tree, AKERR_NULLPOINTER, "tree");
|
||||
akgl_BSPLeaf *leaf = NULL;
|
||||
tree->left = NULL;
|
||||
tree->right = NULL;
|
||||
tree->parent = NULL;
|
||||
leaf = (akgl_BSPLeaf *)tree->leaf;
|
||||
if ( tree->leaf != NULL && leaf->actors != NULL ) {
|
||||
FAIL_RETURN(e, AKERR_VALUE, "Can't release tree node %p until its leaf actors %p is released and leaf->actors == NULL", tree, leaf->actors);
|
||||
} else if ( tree->leaf != NULL ) {
|
||||
memset((void *)tree->leaf, 0x00, sizeof(akgl_BSPLeaf));
|
||||
}
|
||||
tree->leaf = AKGL_LIST_SENTINEL;
|
||||
SUCCEED_RETURN(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Iterator callback which releases a given list item back to the heap
|
||||
*
|
||||
* @param[in] ptr The aksl_ListNode to free
|
||||
* @param[in] data Context data that was passed to aksl_list_iterate
|
||||
*
|
||||
* @throws AKERR_VALUE The aksl_TreeNode contains a leaf that has not been released.
|
||||
* @return akerr_ErrorContext*
|
||||
*/
|
||||
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_heap_iter_list_release(aksl_ListNode *ptr, void *data)
|
||||
{
|
||||
PREPARE_ERROR(e);
|
||||
FAIL_ZERO_RETURN(e, ptr, AKERR_NULLPOINTER, "ptr)");
|
||||
PASS(e, akgl_heap_release_list(ptr));
|
||||
SUCCEED_RETURN(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Iterator callback which releases a given tree node back to the heap. Calls akgl_heap_release_list on the tree leaf as well.
|
||||
*
|
||||
* @param[in] ptr The aksl_TreeNode to free
|
||||
* @param[in] data Context data that was passed to aksl_tree_iterate
|
||||
*
|
||||
* @return akerr_ErrorContext*
|
||||
*/
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_heap_iter_tree_release(aksl_TreeNode *ptr, void *data)
|
||||
{
|
||||
PREPARE_ERROR(e);
|
||||
FAIL_ZERO_RETURN(e, ptr, AKERR_NULLPOINTER, "ptr");
|
||||
if ( ptr->leaf != AKGL_LIST_SENTINEL && ptr->leaf != NULL ) {
|
||||
PASS(e, akgl_heap_release_list(ptr->leaf));
|
||||
//ptr->leaf = NULL;
|
||||
}
|
||||
PASS(e, akgl_heap_release_tree(ptr));
|
||||
SUCCEED_RETURN(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the next actor from the heap
|
||||
*
|
||||
* @param[out] dest The pointer that will hold the procured actor
|
||||
*
|
||||
* @throws AKGL_ERR_OOHEAP There are no available actors in HEAP_ACTOR
|
||||
* @return akerr_ErrorContext*
|
||||
*/
|
||||
akerr_ErrorContext *akgl_heap_next_actor(akgl_Actor **dest)
|
||||
{
|
||||
PREPARE_ERROR(errctx);
|
||||
@@ -55,9 +223,18 @@ akerr_ErrorContext *akgl_heap_next_actor(akgl_Actor **dest)
|
||||
*dest = &HEAP_ACTOR[i];
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
FAIL_RETURN(errctx, AKERR_HEAP, "Unable to find unused actor on the heap");
|
||||
FAIL_RETURN(errctx, AKGL_ERR_OOHEAP, "Unable to find unused actor on the heap");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the next akgl_Sprite from the heap
|
||||
*
|
||||
* @param[out] dest The pointer that will hold the procured sprite
|
||||
*
|
||||
* @throws AKGL_ERR_OOHEAP There are no available actors in HEAP_SPRITE
|
||||
* @return akerr_ErrorContext*
|
||||
*/
|
||||
|
||||
akerr_ErrorContext *akgl_heap_next_sprite(akgl_Sprite **dest)
|
||||
{
|
||||
PREPARE_ERROR(errctx);
|
||||
@@ -68,9 +245,17 @@ akerr_ErrorContext *akgl_heap_next_sprite(akgl_Sprite **dest)
|
||||
*dest = &HEAP_SPRITE[i];
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
FAIL_RETURN(errctx, AKERR_HEAP, "Unable to find unused sprite on the heap");
|
||||
FAIL_RETURN(errctx, AKGL_ERR_OOHEAP, "Unable to find unused sprite on the heap");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the next akgl_SpriteSheet from the heap
|
||||
*
|
||||
* @param[out] dest The pointer that will hold the procured spritesheet
|
||||
*
|
||||
* @throws AKGL_ERR_OOHEAP There are no available elements in HEAP_SPRITESHEET
|
||||
* @return akerr_ErrorContext*
|
||||
*/
|
||||
akerr_ErrorContext *akgl_heap_next_spritesheet(akgl_SpriteSheet **dest)
|
||||
{
|
||||
PREPARE_ERROR(errctx);
|
||||
@@ -81,9 +266,18 @@ akerr_ErrorContext *akgl_heap_next_spritesheet(akgl_SpriteSheet **dest)
|
||||
*dest = &HEAP_SPRITESHEET[i];
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
FAIL_RETURN(errctx, AKERR_HEAP, "Unable to find unused spritesheet on the heap");
|
||||
FAIL_RETURN(errctx, AKGL_ERR_OOHEAP, "Unable to find unused spritesheet on the heap");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the next akgl_Character from the heap
|
||||
*
|
||||
* @param[out] dest The pointer that will hold the procured character
|
||||
*
|
||||
* @throws AKGL_ERR_OOHEAP There are no available elements in HEAP_CHARACTER
|
||||
* @return akerr_ErrorContext*
|
||||
*/
|
||||
|
||||
akerr_ErrorContext *akgl_heap_next_character(akgl_Character **dest)
|
||||
{
|
||||
PREPARE_ERROR(errctx);
|
||||
@@ -94,9 +288,17 @@ akerr_ErrorContext *akgl_heap_next_character(akgl_Character **dest)
|
||||
*dest = &HEAP_CHARACTER[i];
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
FAIL_RETURN(errctx, AKERR_HEAP, "Unable to find unused character on the heap");
|
||||
FAIL_RETURN(errctx, AKGL_ERR_OOHEAP, "Unable to find unused character on the heap");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the next akgl_String from the heap
|
||||
*
|
||||
* @param[out] dest The pointer that will hold the procured string
|
||||
*
|
||||
* @throws AKGL_ERR_OOHEAP There are no available elements in HEAP_STRING
|
||||
* @return akerr_ErrorContext*
|
||||
*/
|
||||
akerr_ErrorContext *akgl_heap_next_string(akgl_String **dest)
|
||||
{
|
||||
PREPARE_ERROR(errctx);
|
||||
@@ -108,9 +310,16 @@ akerr_ErrorContext *akgl_heap_next_string(akgl_String **dest)
|
||||
HEAP_STRING[i].refcount += 1;
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
FAIL_RETURN(errctx, AKERR_HEAP, "Unable to find unused string on the heap");
|
||||
FAIL_RETURN(errctx, AKGL_ERR_OOHEAP, "Unable to find unused string on the heap");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Release an akgl_Actor from the heap to be used again
|
||||
*
|
||||
* @param[in] ptr The object that will be released
|
||||
*
|
||||
* @return akerr_ErrorContext*
|
||||
*/
|
||||
akerr_ErrorContext *akgl_heap_release_actor(akgl_Actor *ptr)
|
||||
{
|
||||
int i = 0;
|
||||
@@ -131,23 +340,37 @@ akerr_ErrorContext *akgl_heap_release_actor(akgl_Actor *ptr)
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
|
||||
akerr_ErrorContext *akgl_heap_release_character(akgl_Character *basechar)
|
||||
/**
|
||||
* @brief Release an akgl_Character from the heap to be used again
|
||||
*
|
||||
* @param[in] ptr The object that will be released
|
||||
*
|
||||
* @return akerr_ErrorContext*
|
||||
*/
|
||||
akerr_ErrorContext *akgl_heap_release_character(akgl_Character *ptr)
|
||||
{
|
||||
PREPARE_ERROR(errctx);
|
||||
akgl_Iterator opflags;
|
||||
FAIL_ZERO_RETURN(errctx, basechar, AKERR_NULLPOINTER, "NULL character reference");
|
||||
FAIL_ZERO_RETURN(errctx, ptr, AKERR_NULLPOINTER, "NULL character reference");
|
||||
AKGL_BITMASK_CLEAR(opflags.flags);
|
||||
|
||||
if ( basechar->refcount > 0 ) {
|
||||
basechar->refcount -= 1;
|
||||
if ( ptr->refcount > 0 ) {
|
||||
ptr->refcount -= 1;
|
||||
}
|
||||
if ( basechar->refcount == 0 ) {
|
||||
SDL_ClearProperty(AKGL_REGISTRY_CHARACTER, (char *)&basechar->name);
|
||||
memset(basechar, 0x00, sizeof(akgl_Character));
|
||||
if ( ptr->refcount == 0 ) {
|
||||
SDL_ClearProperty(AKGL_REGISTRY_CHARACTER, (char *)&ptr->name);
|
||||
memset(ptr, 0x00, sizeof(akgl_Character));
|
||||
}
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Release an akgl_Sprite from the heap to be used again
|
||||
*
|
||||
* @param[in] ptr The object that will be released
|
||||
*
|
||||
* @return akerr_ErrorContext*
|
||||
*/
|
||||
akerr_ErrorContext *akgl_heap_release_sprite(akgl_Sprite *ptr)
|
||||
{
|
||||
PREPARE_ERROR(errctx);
|
||||
@@ -162,6 +385,13 @@ akerr_ErrorContext *akgl_heap_release_sprite(akgl_Sprite *ptr)
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Release an akgl_SpriteSheet from the heap to be used again
|
||||
*
|
||||
* @param[in] ptr The object that will be released
|
||||
*
|
||||
* @return akerr_ErrorContext*
|
||||
*/
|
||||
akerr_ErrorContext *akgl_heap_release_spritesheet(akgl_SpriteSheet *ptr)
|
||||
{
|
||||
PREPARE_ERROR(errctx);
|
||||
@@ -180,6 +410,13 @@ akerr_ErrorContext *akgl_heap_release_spritesheet(akgl_SpriteSheet *ptr)
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Release an akgl_String from the heap to be used again
|
||||
*
|
||||
* @param[in] ptr The object that will be released
|
||||
*
|
||||
* @return akerr_ErrorContext*
|
||||
*/
|
||||
akerr_ErrorContext *akgl_heap_release_string(akgl_String *ptr)
|
||||
{
|
||||
PREPARE_ERROR(errctx);
|
||||
|
||||
@@ -52,6 +52,17 @@ akerr_ErrorContext *akgl_get_json_number_value(json_t *obj, char *key, float *de
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_double_value(json_t *obj, char *key, double *dest)
|
||||
{
|
||||
PREPARE_ERROR(errctx);
|
||||
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "NULL pointer reference");
|
||||
json_t *value = json_object_get(obj, key);
|
||||
FAIL_ZERO_RETURN(errctx, value, AKERR_KEY, "Key %s not found in object", key);
|
||||
FAIL_ZERO_RETURN(errctx, (json_is_number(value)), AKERR_TYPE, "Key %s in object has incorrect type", key);
|
||||
*dest = json_number_value(value);
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
|
||||
akerr_ErrorContext *akgl_get_json_string_value(json_t *obj, char *key, akgl_String **dest)
|
||||
{
|
||||
json_t *value = NULL;
|
||||
@@ -129,3 +140,26 @@ akerr_ErrorContext *akgl_get_json_array_index_string(json_t *array, int index, a
|
||||
strncpy((char *)&(*dest)->data, json_string_value(value), AKGL_MAX_STRING_LENGTH);
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_with_default(akerr_ErrorContext *err, void *defval, void *dest, uint32_t defsize)
|
||||
{
|
||||
PREPARE_ERROR(e);
|
||||
if ( err == NULL ) {
|
||||
SUCCEED_RETURN(e);
|
||||
}
|
||||
int docopy = 0;
|
||||
|
||||
FAIL_ZERO_RETURN(e, err, AKERR_NULLPOINTER, "err");
|
||||
FAIL_ZERO_RETURN(e, defval, AKERR_NULLPOINTER, "defval");
|
||||
FAIL_ZERO_RETURN(e, dest, AKERR_NULLPOINTER, "dest");
|
||||
|
||||
ATTEMPT {
|
||||
} CLEANUP {
|
||||
} PROCESS(err) {
|
||||
} HANDLE_GROUP(err, AKERR_KEY) {
|
||||
} HANDLE_GROUP(err, AKERR_INDEX) {
|
||||
memcpy(dest, defval, defsize);
|
||||
} FINISH(err, true);
|
||||
|
||||
SUCCEED_RETURN(e);
|
||||
}
|
||||
|
||||
239
src/physics.c
239
src/physics.c
@@ -1,3 +1,4 @@
|
||||
#include <math.h>
|
||||
#include <akstdlib.h>
|
||||
#include <akgl/physics.h>
|
||||
#include <akgl/actor.h>
|
||||
@@ -5,8 +6,9 @@
|
||||
#include <akgl/error.h>
|
||||
#include <akgl/heap.h>
|
||||
#include <akgl/registry.h>
|
||||
#include <akgl/stage.h>
|
||||
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_null_gravity(akgl_PhysicsBackend *self, akgl_Actor *actor, SDL_Time curtime)
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_null_gravity(akgl_PhysicsBackend *self, akgl_Actor *actor, float32_t dt)
|
||||
{
|
||||
PREPARE_ERROR(e);
|
||||
FAIL_ZERO_RETURN(e, self, AKERR_NULLPOINTER, "self");
|
||||
@@ -20,7 +22,7 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_null_collide(akgl_PhysicsBackend
|
||||
SUCCEED_RETURN(e);
|
||||
}
|
||||
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_null_move(struct akgl_PhysicsBackend *self, akgl_Actor *actor, SDL_Time curtime)
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_null_move(struct akgl_PhysicsBackend *self, akgl_Actor *actor, float32_t dt)
|
||||
{
|
||||
PREPARE_ERROR(e);
|
||||
FAIL_ZERO_RETURN(e, self, AKERR_NULLPOINTER, "self");
|
||||
@@ -41,85 +43,79 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_init_null(akgl_PhysicsBackend *s
|
||||
}
|
||||
|
||||
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_ss_gravity(akgl_PhysicsBackend *self, akgl_Actor *actor, SDL_Time curtime)
|
||||
{
|
||||
PREPARE_ERROR(e);
|
||||
FAIL_ZERO_RETURN(e, self, AKERR_NULLPOINTER, "self");
|
||||
// Do nothing
|
||||
// Calculate the drop of all relevant actors which is a function of their mass and the
|
||||
// world's gravity
|
||||
|
||||
//Gravity is applied in units per second. So we apply
|
||||
// (unit / milliseconds per second) * (milliseconds since last update)
|
||||
actor->vx += ((self->gravity_x / AKGL_TIME_ONESEC_NS) * (curtime - self->gravity_time));
|
||||
actor->vy += ((self->gravity_y / AKGL_TIME_ONESEC_NS) * (curtime - self->gravity_time));
|
||||
actor->vz += ((self->gravity_z / AKGL_TIME_ONESEC_NS) * (curtime - self->gravity_time));
|
||||
|
||||
// Apply atmospheric drag
|
||||
actor->vx -= actor->vx * self->drag_x * (curtime - self->gravity_time);
|
||||
actor->vy -= actor->vy * self->drag_x * (curtime - self->gravity_time);
|
||||
actor->vz -= actor->vz * self->drag_x * (curtime - self->gravity_time);
|
||||
// Need a euler function
|
||||
SUCCEED_RETURN(e);
|
||||
}
|
||||
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_ss_collide(akgl_PhysicsBackend *self, akgl_Actor *a1, akgl_Actor *a2)
|
||||
{
|
||||
PREPARE_ERROR(e);
|
||||
FAIL_ZERO_RETURN(e, self, AKERR_NULLPOINTER, "self");
|
||||
FAIL_RETURN(e, AKERR_API, "Not implemented");
|
||||
SUCCEED_RETURN(e);
|
||||
}
|
||||
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_ss_move(struct akgl_PhysicsBackend *self, akgl_Actor *actor, SDL_Time curtime)
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_arcade_gravity(akgl_PhysicsBackend *self, akgl_Actor *actor, float32_t dt)
|
||||
{
|
||||
PREPARE_ERROR(e);
|
||||
FAIL_ZERO_RETURN(e, self, AKERR_NULLPOINTER, "self");
|
||||
FAIL_ZERO_RETURN(e, actor, AKERR_NULLPOINTER, "actor");
|
||||
|
||||
if ( actor->parent != NULL ) {
|
||||
// Children don't move independently of their parents, they just have an offset
|
||||
SUCCEED_RETURN(e);
|
||||
} else if ( actor->basechar == NULL ) {
|
||||
SUCCEED_RETURN(e);
|
||||
} else {
|
||||
if ( (curtime - actor->movetimer) >= actor->basechar->speedtime ) {
|
||||
actor->movetimer = curtime;
|
||||
ATTEMPT {
|
||||
CATCH(e, actor->movementlogicfunc(actor,curtime));
|
||||
} CLEANUP {
|
||||
} PROCESS(e) {
|
||||
} HANDLE(e, AKGL_ERR_LOGICINTERRUPT) {
|
||||
// The actor told us NOT to process them, they handled their own update
|
||||
SUCCEED_RETURN(e);
|
||||
} FINISH(e, true);
|
||||
if ( AKGL_BITMASK_HAS(actor->state, AKGL_ACTOR_STATE_MOVING_LEFT) ) {
|
||||
actor->x += -actor->vx;
|
||||
}
|
||||
if ( AKGL_BITMASK_HAS(actor->state, AKGL_ACTOR_STATE_MOVING_RIGHT) ) {
|
||||
actor->x += actor->vx;
|
||||
}
|
||||
if ( AKGL_BITMASK_HAS(actor->state, AKGL_ACTOR_STATE_MOVING_UP) ) {
|
||||
actor->y += -actor->vy;
|
||||
}
|
||||
if ( AKGL_BITMASK_HAS(actor->state, AKGL_ACTOR_STATE_MOVING_DOWN) ) {
|
||||
actor->y += actor->vy;
|
||||
}
|
||||
}
|
||||
if ( self->gravity_x != 0 ) {
|
||||
// Assume the X origin is - (screen left)
|
||||
actor->ex -= (self->gravity_x * dt);
|
||||
}
|
||||
if ( self->gravity_y != 0 ) {
|
||||
// Assume Y origin is + (down screen)
|
||||
actor->ey += (self->gravity_y * dt);
|
||||
}
|
||||
if ( self->gravity_z != 0 ) {
|
||||
// Assume Z origin is - (behind the camera)
|
||||
actor->ez -= (self->gravity_z * dt);
|
||||
}
|
||||
|
||||
SUCCEED_RETURN(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Test two actors for collision
|
||||
*
|
||||
* @param[in] self The physics simulation to use
|
||||
* @param[in] a1 actor 1
|
||||
* @param[in] a2 actor 2
|
||||
*
|
||||
* @throws AKERR_NULLPOINTER on null pointer input
|
||||
*
|
||||
* @return akerr_ErrorContext*
|
||||
*/
|
||||
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_arcade_collide(akgl_PhysicsBackend *self, akgl_Actor *a1, akgl_Actor *a2)
|
||||
{
|
||||
PREPARE_ERROR(e);
|
||||
FAIL_ZERO_RETURN(e, self, AKERR_NULLPOINTER, "self");
|
||||
FAIL_ZERO_RETURN(e, a1, AKERR_NULLPOINTER, "a1");
|
||||
FAIL_ZERO_RETURN(e, a2, AKERR_NULLPOINTER, "a2");
|
||||
FAIL_RETURN(e, AKERR_API, "Not implemented");
|
||||
SUCCEED_RETURN(e);
|
||||
}
|
||||
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_arcade_move(struct akgl_PhysicsBackend *self, akgl_Actor *actor, float32_t dt)
|
||||
{
|
||||
PREPARE_ERROR(e);
|
||||
FAIL_ZERO_RETURN(e, self, AKERR_NULLPOINTER, "self");
|
||||
FAIL_ZERO_RETURN(e, actor, AKERR_NULLPOINTER, "actor");
|
||||
akgl_Sprite *curspr = NULL;
|
||||
actor->x += actor->vx * dt;
|
||||
actor->y += actor->vy * dt;
|
||||
actor->z += actor->vz * dt;
|
||||
// Set the actor's bounding box for physics
|
||||
if ( actor->basechar != NULL ) {
|
||||
PASS(e, actor->basechar->sprite_get(actor->basechar, actor->state, &curspr));
|
||||
actor->bbox = (SDL_FRect){actor->x, actor->y, curspr->width, curspr->height};
|
||||
} else {
|
||||
actor->bbox = (SDL_FRect){actor->x, actor->y, 0, 0};
|
||||
}
|
||||
SUCCEED_RETURN(e);
|
||||
}
|
||||
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_init_sidescroller(akgl_PhysicsBackend *self)
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_init_arcade(akgl_PhysicsBackend *self)
|
||||
{
|
||||
akgl_String *tmp;
|
||||
PREPARE_ERROR(e);
|
||||
FAIL_ZERO_RETURN(e, self, AKERR_NULLPOINTER, "self");
|
||||
PASS(e, akgl_heap_next_string(&tmp));
|
||||
|
||||
self->gravity = akgl_physics_ss_gravity;
|
||||
self->collide = akgl_physics_ss_collide;
|
||||
self->move = akgl_physics_ss_move;
|
||||
self->gravity = akgl_physics_arcade_gravity;
|
||||
self->collide = akgl_physics_arcade_collide;
|
||||
self->move = akgl_physics_arcade_move;
|
||||
self->simulate = akgl_physics_simulate;
|
||||
|
||||
ATTEMPT {
|
||||
@@ -143,6 +139,17 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_init_sidescroller(akgl_PhysicsBa
|
||||
SUCCEED_RETURN(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Perform arcade physics simulation on all alive actors
|
||||
*
|
||||
* @param[in] self Physics simulator object
|
||||
* @param[in] opflags Iteration operation flags (or NULL)
|
||||
*
|
||||
* @throws AKERR_NULLPOINTER on null pointer input
|
||||
*
|
||||
* @return akerr_ErrorContext*
|
||||
*/
|
||||
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_simulate(akgl_PhysicsBackend *self, akgl_Iterator *opflags)
|
||||
{
|
||||
PREPARE_ERROR(e);
|
||||
@@ -151,6 +158,7 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_simulate(akgl_PhysicsBackend *se
|
||||
.layerid = 0
|
||||
};
|
||||
SDL_Time curtime = SDL_GetTicksNS();
|
||||
float32_t dt = (float32_t)(curtime - self->gravity_time) / (float32_t)AKGL_TIME_ONESEC_NS;
|
||||
akgl_Actor *actor = NULL;
|
||||
|
||||
FAIL_ZERO_RETURN(e, self, AKERR_NULLPOINTER, "self");
|
||||
@@ -160,27 +168,116 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_simulate(akgl_PhysicsBackend *se
|
||||
opflags = &defflags;
|
||||
}
|
||||
|
||||
|
||||
for ( int i = 0; i < AKGL_MAX_HEAP_ACTOR; i++ ) {
|
||||
actor = &HEAP_ACTOR[i];
|
||||
if ( actor->refcount == 0 ) {
|
||||
continue;
|
||||
}
|
||||
if ( actor->parent != NULL ) {
|
||||
// Children don't move independently of their parents, they just have an offset
|
||||
actor->x = actor->parent->x + actor->vx;
|
||||
actor->y = actor->parent->y + actor->vy;
|
||||
actor->z = actor->parent->z + actor->vz;
|
||||
continue;
|
||||
} else if ( actor->basechar == NULL ) {
|
||||
continue;
|
||||
}
|
||||
if ( AKGL_BITMASK_HAS(opflags->flags, AKGL_ITERATOR_OP_LAYERMASK) ) {
|
||||
if ( actor->layer != opflags->layerid ) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// thrust is a function of acceleration on a given axis
|
||||
if ( AKGL_BITMASK_HAS(actor->state, AKGL_ACTOR_STATE_MOVING_LEFT) ||
|
||||
AKGL_BITMASK_HAS(actor->state, AKGL_ACTOR_STATE_MOVING_RIGHT) ) {
|
||||
actor->vx += actor->basechar->ax;
|
||||
actor->tx += actor->ax * dt;
|
||||
}
|
||||
if ( AKGL_BITMASK_HAS(actor->state, AKGL_ACTOR_STATE_MOVING_UP) ||
|
||||
AKGL_BITMASK_HAS(actor->state, AKGL_ACTOR_STATE_MOVING_DOWN) ) {
|
||||
actor->vy += actor->basechar->ay;
|
||||
actor->ty += actor->ay * dt;
|
||||
}
|
||||
PASS(e, self->gravity(self, actor, curtime));
|
||||
PASS(e, self->move(self, actor, curtime));
|
||||
self->gravity_time = curtime;
|
||||
|
||||
// velocity equals thrust unless thrust exceeds max speed
|
||||
if ( fabsf(actor->tx) > fabsf(actor->sx) ) {
|
||||
if ( actor->tx < 0 ) {
|
||||
actor->tx = -actor->sx;
|
||||
} else {
|
||||
actor->tx = actor->sx;
|
||||
}
|
||||
}
|
||||
if ( fabsf(actor->ty) > fabsf(actor->sy) ) {
|
||||
if ( actor->ty < 0 ) {
|
||||
actor->ty = -actor->sy;
|
||||
} else {
|
||||
actor->ty = actor->sy;
|
||||
}
|
||||
}
|
||||
if ( fabsf(actor->tz) > fabsf(actor->sz) ) {
|
||||
if ( actor->tz < 0 ) {
|
||||
actor->tz = -actor->sz;
|
||||
} else {
|
||||
actor->tz = actor->sz;
|
||||
}
|
||||
}
|
||||
ATTEMPT {
|
||||
CATCH(e, actor->movementlogicfunc(actor, dt));
|
||||
} CLEANUP {
|
||||
} PROCESS(e) {
|
||||
} HANDLE(e, AKGL_ERR_LOGICINTERRUPT) {
|
||||
// noop
|
||||
} FINISH(e, true);
|
||||
|
||||
PASS(e, self->gravity(self, actor, dt));
|
||||
|
||||
// Counteract velocity with atmospheric drag
|
||||
if ( self->drag_x != 0 ) {
|
||||
actor->ex -= actor->ex * self->drag_x * dt;
|
||||
}
|
||||
if ( self->drag_y != 0 ) {
|
||||
actor->ey -= actor->ey * self->drag_y * dt;
|
||||
}
|
||||
if ( self->drag_z != 0 ) {
|
||||
actor->ez -= actor->ez * self->drag_z * dt;
|
||||
}
|
||||
|
||||
actor->vx = actor->ex + actor->tx;
|
||||
actor->vy = actor->ey + actor->ty;
|
||||
actor->vz = actor->ez + actor->tz;
|
||||
|
||||
PASS(e, self->move(self, actor, dt));
|
||||
PASS(e, stage->partition_actor(stage, actor));
|
||||
}
|
||||
self->gravity_time = curtime;
|
||||
SUCCEED_RETURN(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize a physics backend according to a string type
|
||||
*
|
||||
* @param[out] self The physics backend to initialize
|
||||
* @param[in] type The type to initialize
|
||||
*
|
||||
* @throws AKERR_NULLPOINTER on null pointer input
|
||||
* @throws AKERR_KEY on invalid type
|
||||
*
|
||||
* @return akerr_ErrorContext*
|
||||
*/
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_factory(akgl_PhysicsBackend *self, akgl_String *type)
|
||||
{
|
||||
uint32_t hashval;
|
||||
PREPARE_ERROR(e);
|
||||
FAIL_ZERO_RETURN(e, self, AKERR_NULLPOINTER, "self");
|
||||
FAIL_ZERO_RETURN(e, type, AKERR_NULLPOINTER, "type");
|
||||
|
||||
if ( strncmp(type->data, "null", 4) == 0) {
|
||||
PASS(e, akgl_physics_init_null(self));
|
||||
SUCCEED_RETURN(e);
|
||||
}
|
||||
if ( strncmp(type->data, "arcade", 6) == 0) {
|
||||
PASS(e, akgl_physics_init_arcade(self));
|
||||
SUCCEED_RETURN(e);
|
||||
}
|
||||
FAIL_RETURN(e, AKERR_KEY, "Invalid physics engine %s", type->data);
|
||||
}
|
||||
|
||||
@@ -33,10 +33,10 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_render_init2d(akgl_RenderBackend *self)
|
||||
"Couldn't create window/renderer: %s",
|
||||
SDL_GetError());
|
||||
|
||||
camera.x = 0;
|
||||
camera.y = 0;
|
||||
camera.w = screenwidth;
|
||||
camera.h = screenheight;
|
||||
camera->x = 0;
|
||||
camera->y = 0;
|
||||
camera->w = screenwidth;
|
||||
camera->h = screenheight;
|
||||
|
||||
self->shutdown = &akgl_render_2d_shutdown;
|
||||
self->frame_start = &akgl_render_2d_frame_start;
|
||||
@@ -117,8 +117,8 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_render_2d_draw_world(akgl_RenderBackend
|
||||
PASS(e, aksl_memset((void *)opflags, 0x00, sizeof(akgl_Iterator)));
|
||||
}
|
||||
for ( int i = 0; i < AKGL_TILEMAP_MAX_LAYERS ; i++ ) {
|
||||
if ( i < gamemap.numlayers ) {
|
||||
PASS(e, akgl_tilemap_draw((akgl_Tilemap *)&gamemap, &camera, i));
|
||||
if ( i < gamemap->numlayers ) {
|
||||
PASS(e, akgl_tilemap_draw(gamemap, camera, i));
|
||||
}
|
||||
for ( int j = 0; j < AKGL_MAX_HEAP_ACTOR ; j++ ) {
|
||||
actor = &HEAP_ACTOR[j];
|
||||
|
||||
@@ -174,7 +174,7 @@ akerr_ErrorContext *akgl_spritesheet_initialize(akgl_SpriteSheet *sheet, int spr
|
||||
strncpy((char *)&sheet->name, filename, AKGL_SPRITE_SHEET_MAX_FILENAME_LENGTH);
|
||||
|
||||
//snprintf((char *)&tmpstr->data, AKGL_MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), filename);
|
||||
sheet->texture = IMG_LoadTexture(renderer.sdl_renderer, filename);
|
||||
sheet->texture = IMG_LoadTexture(renderer->sdl_renderer, filename);
|
||||
FAIL_ZERO_BREAK(errctx, sheet->texture, AKGL_ERR_SDL, "Failed loading asset %s : %s", filename, SDL_GetError());
|
||||
|
||||
FAIL_ZERO_BREAK(
|
||||
|
||||
373
src/stage.c
Normal file
373
src/stage.c
Normal file
@@ -0,0 +1,373 @@
|
||||
#include <SDL3/SDL.h>
|
||||
#include <akstdlib.h>
|
||||
#include <akgl/stage.h>
|
||||
#include <akgl/actor.h>
|
||||
#include <akgl/heap.h>
|
||||
#include <akgl/game.h>
|
||||
|
||||
/**
|
||||
* @brief Initialize a 2D stage
|
||||
*
|
||||
* @param[in] self akgl_Stage * to initialize
|
||||
*
|
||||
* @throw AKERR_NULLPOINTER on null input pointers
|
||||
* @return akerr_ErrorContext
|
||||
*/
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_stage_2d(akgl_Stage *self)
|
||||
{
|
||||
PREPARE_ERROR(e);
|
||||
FAIL_ZERO_RETURN(e, self, AKERR_NULLPOINTER, "self");
|
||||
memset((void *)self, 0x00, sizeof(akgl_Stage));
|
||||
self->partition = akgl_stage_2d_partition;
|
||||
self->partition_actor = akgl_stage_2d_bsp_move;
|
||||
memset((void *)&self->bsp, 0x00, sizeof(aksl_TreeNode));
|
||||
self->bsp.leaf = &self->_rootleaf;
|
||||
memset((void *)&self->_rootleaf, 0x00, sizeof(akgl_BSPLeaf));
|
||||
SUCCEED_RETURN(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Flip the current partitioning direction
|
||||
*
|
||||
* @param[in] One of AKGL_STAGE_PARTITION_HORIZONTAL or AKGL_STAGE_PARTITION_VERTICAL
|
||||
* @param[out] dest Location to place the modified direction
|
||||
*
|
||||
* @throws AKERR_NULLPOINTER on null pointer inputs
|
||||
* @throws AKERR_VALUE on invalid direction
|
||||
* @return akerr_ErrorContext*
|
||||
*/
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_stage_2d_partition_switchdirection(uint8_t direction, uint8_t *dest)
|
||||
{
|
||||
PREPARE_ERROR(e);
|
||||
FAIL_ZERO_RETURN(e, dest, AKERR_NULLPOINTER, "dest");
|
||||
if ( direction == AKGL_STAGE_PARTITION_HORIZONTAL ) {
|
||||
*dest = AKGL_STAGE_PARTITION_VERTICAL;
|
||||
} else if ( direction == AKGL_STAGE_PARTITION_VERTICAL ) {
|
||||
*dest = AKGL_STAGE_PARTITION_HORIZONTAL;
|
||||
} else {
|
||||
FAIL_RETURN(e, AKERR_VALUE, "Unknown partition direction %d", direction);
|
||||
}
|
||||
SUCCEED_RETURN(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Iterator function that sorts an actor into one of three lists based on colliding rectangles
|
||||
*
|
||||
* This function tests which of two rectangles ("left" and "right") in the context collide with the actor.
|
||||
* The actor is sorted into the appropriate linked list for each given rectangle.
|
||||
* If the actor collides with neither rectangle, it is pushed onto the parent list.
|
||||
* Note that the existing node is not pushed - a new node is taken from the heap and pushed.
|
||||
* Otherwise we would have to pop the actor out of whatever list it was in, which would
|
||||
* modify the list during iteration.
|
||||
*
|
||||
* @param[in] node A list node containing an akgl_Actor in ->data
|
||||
* @param[in] data A pointer to akgl_BSPContext containing left, right, and parent SDL_FRect structures
|
||||
*
|
||||
* @throws AKERR_NULLPOINTER on null pointer inputs
|
||||
* @return akerr_ErrorContext*
|
||||
*/
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_stage_2d_bsp_actoriter(aksl_ListNode *node, void *data)
|
||||
{
|
||||
bool e1intersect;
|
||||
bool e2intersect;
|
||||
akgl_BSPContext *context = NULL;
|
||||
akgl_Actor *actor = NULL;
|
||||
aksl_TreeNode *dest = NULL;
|
||||
aksl_ListNode *newnode = NULL;
|
||||
akgl_BSPLeaf *leaf = NULL;
|
||||
|
||||
PREPARE_ERROR(e);
|
||||
FAIL_ZERO_RETURN(e, node, AKERR_NULLPOINTER, "node");
|
||||
FAIL_ZERO_RETURN(e, data, AKERR_NULLPOINTER, "data");
|
||||
FAIL_ZERO_RETURN(e, node->data, AKERR_NULLPOINTER, "node->data");
|
||||
context = (akgl_BSPContext *)data;
|
||||
actor = (akgl_Actor *)node->data;
|
||||
|
||||
FAIL_ZERO_RETURN(e, context->left, AKERR_NULLPOINTER, "left");
|
||||
FAIL_ZERO_RETURN(e, context->right, AKERR_NULLPOINTER, "right");
|
||||
FAIL_ZERO_RETURN(e, context->parent, AKERR_NULLPOINTER, "parent");
|
||||
FAIL_ZERO_RETURN(e, ((akgl_BSPLeaf *)context->left->leaf)->actors, AKERR_NULLPOINTER, "left->leaf");
|
||||
FAIL_ZERO_RETURN(e, ((akgl_BSPLeaf *)context->right->leaf)->actors, AKERR_NULLPOINTER, "right->leaf");
|
||||
FAIL_ZERO_RETURN(e, ((akgl_BSPLeaf *)context->parent->leaf)->actors, AKERR_NULLPOINTER, "parent->leaf");
|
||||
|
||||
|
||||
leaf = (akgl_BSPLeaf *)context->left->leaf;
|
||||
e1intersect = SDL_HasRectIntersectionFloat(&leaf->extent, &actor->bbox);
|
||||
leaf = (akgl_BSPLeaf *)context->right->leaf;
|
||||
e2intersect = SDL_HasRectIntersectionFloat(&leaf->extent, &actor->bbox);
|
||||
|
||||
if ( e1intersect && e2intersect ) {
|
||||
// Actors who cross left/right boundaries get left in the context of their parent, so both
|
||||
// child spaces test them for collision
|
||||
dest = context->parent;
|
||||
} else if ( e1intersect ) {
|
||||
dest = context->left;
|
||||
} else if ( e2intersect ) {
|
||||
dest = context->right;
|
||||
}
|
||||
|
||||
if ( dest != NULL ) {
|
||||
PASS(e, akgl_heap_next_list(&newnode));
|
||||
newnode->data = node->data;
|
||||
leaf = (akgl_BSPLeaf *)dest->leaf;
|
||||
PASS(e, aksl_list_push(leaf->actors, newnode));
|
||||
actor->bsphome = dest;
|
||||
actor->bsplistnode = newnode;
|
||||
}
|
||||
|
||||
SUCCEED_RETURN(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Recursive function used to divide the stage into a BSP tree of actor near neighbors
|
||||
*
|
||||
* This is a recursive function that builds a balanced tree until the tree is maxdepth levels deep.
|
||||
* It creates a list of all actors which fit within the extents of the root node,
|
||||
* then successively divides that actor list down into the extents of the child nodes of the balanced tree,
|
||||
* until the maximum recursion depth has been achieved.
|
||||
*
|
||||
* @param[in] root The root node of the current level of the tree
|
||||
* @param[in] actors The list of all actors that are within the root node's extents
|
||||
* @param[in] extents The {x, y, w, h} extents of this level of the tree
|
||||
* @param[in] direction The AKL_STAGE_PARTITION_* direction in which the extent is being divided
|
||||
* @param[in] depth The depth of the current root node. Callers should provide 1 here.
|
||||
* @param[in] maxdepth The maximum depth to which we should recurse
|
||||
*
|
||||
* @throws AKERR_VALUE Invalid direction provided
|
||||
*
|
||||
* @return akerr_ErrorContext*
|
||||
*/
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_stage_2d_bsp(aksl_TreeNode *root, aksl_ListNode *actors, SDL_FRect extents, uint8_t direction, uint8_t depth, uint8_t maxdepth)
|
||||
{
|
||||
akgl_BSPContext context = {0, 0, 0};
|
||||
akgl_BSPLeaf *leaf = NULL;
|
||||
|
||||
// Until we have reached maxdepth levels of depth
|
||||
PREPARE_ERROR(e);
|
||||
if ( depth > maxdepth ) {
|
||||
SUCCEED_RETURN(e);
|
||||
}
|
||||
|
||||
// - Get a pointer to the left and right nodes of the tree representing the halves
|
||||
// - Divide the current working space into two equal halves
|
||||
// - Construct a SDL_FRect representing the two equal halves
|
||||
// (the top half of a vertical division is "left", bottom half is "right")
|
||||
if ( root->left == NULL ) {
|
||||
PASS(e, akgl_heap_next_tree((aksl_TreeNode **)&root->left));
|
||||
PASS(e, akgl_heap_next_list((aksl_ListNode **)&((akgl_BSPLeaf *)root->left->leaf)->actors));
|
||||
root->left->parent = root;
|
||||
leaf = root->left->leaf;
|
||||
if ( direction == AKGL_STAGE_PARTITION_HORIZONTAL ) {
|
||||
leaf->extent.x = extents.x;
|
||||
leaf->extent.y = extents.y;
|
||||
leaf->extent.w = extents.w;
|
||||
leaf->extent.h = (extents.h / 2);
|
||||
} else if ( direction == AKGL_STAGE_PARTITION_VERTICAL ) {
|
||||
leaf->extent.x = extents.x;
|
||||
leaf->extent.y = extents.y;
|
||||
leaf->extent.w = (extents.w / 2);
|
||||
leaf->extent.h = extents.h;
|
||||
} else {
|
||||
FAIL_RETURN(e, AKERR_VALUE, "Invalid partition direction %d", direction);
|
||||
}
|
||||
}
|
||||
if ( root->right == NULL ) {
|
||||
PASS(e, akgl_heap_next_tree((aksl_TreeNode **)&root->right));
|
||||
PASS(e, akgl_heap_next_list((aksl_ListNode **)&((akgl_BSPLeaf *)root->right->leaf)->actors));
|
||||
root->right->parent = root;
|
||||
leaf = root->right->leaf;
|
||||
if ( direction == AKGL_STAGE_PARTITION_HORIZONTAL ) {
|
||||
leaf->extent.x = extents.x;
|
||||
leaf->extent.y = extents.y + (extents.h / 2);
|
||||
leaf->extent.w = extents.w;
|
||||
leaf->extent.h = (extents.h / 2);
|
||||
} else if ( direction == AKGL_STAGE_PARTITION_VERTICAL ) {
|
||||
leaf->extent.x = extents.x + (extents.w / 2);
|
||||
leaf->extent.y = extents.y;
|
||||
leaf->extent.w = (extents.w / 2);
|
||||
leaf->extent.h = extents.h;
|
||||
} else {
|
||||
FAIL_RETURN(e, AKERR_VALUE, "Invalid partition direction %d", direction);
|
||||
}
|
||||
}
|
||||
if ( ((akgl_BSPLeaf *)root->leaf)->actors == NULL ) {
|
||||
PASS(e, akgl_heap_next_list((aksl_ListNode **)&((akgl_BSPLeaf *)root->leaf)->actors));
|
||||
}
|
||||
context.left = root->left;
|
||||
context.right = root->right;
|
||||
context.parent = root;
|
||||
|
||||
// - Test (SDL_HasIntersection) all actor objects in the current working space
|
||||
// against the SDL_Frects for both halves. If they intersect, push the actors
|
||||
// down into the leaf linked lists for each half
|
||||
ATTEMPT {
|
||||
CATCH(e, aksl_list_iterate(actors, &akgl_stage_2d_bsp_actoriter, &context));
|
||||
} CLEANUP {
|
||||
} PROCESS(e) {
|
||||
} HANDLE(e, AKERR_NULLPOINTER) {
|
||||
SDL_Log("Empty actor list");
|
||||
} FINISH(e, true);
|
||||
|
||||
PASS(e, akgl_stage_2d_partition_switchdirection(direction, &direction));
|
||||
// - Recurse down into the left BSP node, changing our partitioning
|
||||
// (vertical->horizontal, horizontal->vertical etc)
|
||||
PASS(e, akgl_stage_2d_bsp(root->left, ((akgl_BSPLeaf *)root->left->leaf)->actors, ((akgl_BSPLeaf *)context.left->leaf)->extent, direction, depth + 1, maxdepth));
|
||||
// - Recurse down into the right BSP node
|
||||
// (vertical->horizontal, horizontal->vertical etc)
|
||||
PASS(e, akgl_stage_2d_bsp(root->right, ((akgl_BSPLeaf *)root->right->leaf)->actors, ((akgl_BSPLeaf *)context.right->leaf)->extent, direction, depth + 1, maxdepth));
|
||||
|
||||
SUCCEED_RETURN(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Release the stage's curent BSP tree
|
||||
*
|
||||
* This recursive function traverses down all nodes of the stage's BSP tree and release all the tree and list nodes
|
||||
*
|
||||
* @param[in] self The stage whose BSP tree should be freed
|
||||
*
|
||||
* @throws AKERR_NULLPOINTER on NULL pointer inputs
|
||||
*
|
||||
* @return akerr_ErrorContext*
|
||||
*/
|
||||
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_stage_2d_bspfree(akgl_Stage *self)
|
||||
{
|
||||
PREPARE_ERROR(e);
|
||||
FAIL_ZERO_RETURN(e, self, AKERR_NULLPOINTER, "self");
|
||||
PASS(e, aksl_tree_iterate(&self->bsp, &akgl_heap_iter_tree_release, NULL, NULL, AKSL_TREE_SEARCH_DFS, NULL, NULL));
|
||||
SUCCEED_RETURN(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Partition the stage into a BSP tree, grouping near neighbor actors together
|
||||
*
|
||||
* @param[in] self The stage to partition
|
||||
*
|
||||
* @return akerr_ErrorContext*
|
||||
*/
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_stage_2d_partition(akgl_Stage *self)
|
||||
{
|
||||
aksl_ListNode *actors = NULL;
|
||||
aksl_ListNode *curnode = NULL;
|
||||
PREPARE_ERROR(e);
|
||||
FAIL_ZERO_RETURN(e, self, AKERR_NULLPOINTER, "self");
|
||||
|
||||
PASS(e, akgl_stage_2d_bspfree(self));
|
||||
|
||||
self->bsp.leaf = &self->_rootleaf;
|
||||
memset((void *)&self->_rootleaf, 0x00, sizeof(akgl_BSPLeaf));
|
||||
|
||||
// Build a linked list of all actors currently initialized
|
||||
PASS(e, akgl_heap_next_list(&actors));
|
||||
curnode = actors;
|
||||
for ( int i = 0; i < AKGL_MAX_HEAP_ACTOR; i++ ) {
|
||||
if ( HEAP_ACTOR[i].refcount != 0 ) {
|
||||
curnode->data = (void *)&HEAP_ACTOR[i];
|
||||
PASS(e, akgl_heap_next_list(&curnode->next));
|
||||
curnode = curnode->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* This could be better.
|
||||
* Right now we divide the extents into 16 equal rectangles and sort actors
|
||||
* into them by their bbox coordinates. This doesn't help when lots of actors are
|
||||
* stacked up unequally on one area of the screen. A better solution might be to
|
||||
* continue subdividing a given extent until it is small enough that only
|
||||
* N number of actors fit inside of it. All of this is overkill for something like
|
||||
* a simple Mario style sidescroller or even a JRPG, but for something like
|
||||
* a bullet hell, it will be essential.
|
||||
*/
|
||||
((akgl_BSPLeaf *)self->bsp.leaf)->extent = (SDL_FRect){0, 0, camera->w, camera->h};
|
||||
ATTEMPT {
|
||||
CATCH(e, akgl_stage_2d_bsp(
|
||||
&self->bsp,
|
||||
actors,
|
||||
// Define the current working space as the boundaries of the entire stage
|
||||
// (from the origin to the extents of the largest and/or furthest object)
|
||||
// .... let's see what we get if we just cheat and use the camera extents.
|
||||
// (Do we *really* want off-screen objects in the collision detection?)
|
||||
(SDL_FRect){0.0, 0.0, camera->w, camera->h},
|
||||
// Define if we are partitioning horizontally or vertically
|
||||
AKGL_STAGE_PARTITION_VERTICAL,
|
||||
// Begin depth counter at 1
|
||||
1,
|
||||
// Maximum recursion depth
|
||||
AKGL_STAGE_PARTITION_MAXDEPTH)
|
||||
);
|
||||
} CLEANUP {
|
||||
PREPARE_ERROR(e2);
|
||||
PASS(e2, aksl_list_iterate(actors, &akgl_heap_iter_list_release, NULL));
|
||||
} PROCESS(e) {
|
||||
} FINISH(e, true);
|
||||
|
||||
SUCCEED_RETURN(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Move this actor to the correct part of the BSP tree
|
||||
*
|
||||
* @param[in] self akgl_Stage *
|
||||
* @param[in] actor akgl_Actor *
|
||||
*
|
||||
* @throws AKERR_NULLPOINTER on null pointer inputs
|
||||
* @return akerr_ErrorContext
|
||||
*/
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_stage_2d_bsp_move(akgl_Stage *self, akgl_Actor *actor)
|
||||
{
|
||||
aksl_ListNode *tmp = NULL;
|
||||
aksl_TreeNode *curnode = NULL;
|
||||
akgl_BSPContext context;
|
||||
PREPARE_ERROR(e);
|
||||
FAIL_ZERO_RETURN(e, self, AKERR_NULLPOINTER, "self");
|
||||
FAIL_ZERO_RETURN(e, actor, AKERR_NULLPOINTER, "actor");
|
||||
if ( actor->bsphome == NULL ) {
|
||||
// New actor that is not currently part of the BSP tree. Push it down.
|
||||
PASS(e, akgl_heap_next_list(&tmp));
|
||||
tmp->data = actor;
|
||||
ATTEMPT {
|
||||
PASS(e, akgl_stage_2d_bsp(
|
||||
&self->bsp,
|
||||
tmp,
|
||||
(SDL_FRect){0.0, 0.0, camera->w, camera->h},
|
||||
AKGL_STAGE_PARTITION_VERTICAL,
|
||||
1,
|
||||
AKGL_STAGE_PARTITION_MAXDEPTH)
|
||||
);
|
||||
} CLEANUP {
|
||||
PREPARE_ERROR(e2);
|
||||
PASS(e2, akgl_heap_release_list(tmp));
|
||||
} PROCESS(e) {
|
||||
} FINISH(e, true);
|
||||
} else {
|
||||
// Actor already exists somewhere in the BSP tree
|
||||
// 1. Is it still in the extents for its bsphome? If so, do nothing.
|
||||
if ( SDL_HasRectIntersectionFloat(&((akgl_BSPLeaf *)actor->bsphome->leaf)->extent, &actor->bbox) ) {
|
||||
SUCCEED_RETURN(e);
|
||||
}
|
||||
// 2. If not, pop the actor out of its current BSP actor list, and start walking up.
|
||||
PASS(e, aksl_list_pop(actor->bsplistnode));
|
||||
curnode = actor->bsphome->parent;
|
||||
tmp = actor->bsplistnode;
|
||||
while ( curnode != NULL ) {
|
||||
// 3. Is it within the current BSP node's extents? If not, walk up and repeat.
|
||||
if ( SDL_HasRectIntersectionFloat(&((akgl_BSPLeaf *)curnode->leaf)->extent, &actor->bbox) ) {
|
||||
// 4. Find which extent it matches.
|
||||
// FIXME : akgl_BSPContext should be replaced with aksl_TreeNode at this point, it's fully redundant
|
||||
context.left = curnode->left;
|
||||
context.right = curnode->right;
|
||||
context.parent = curnode->parent;
|
||||
PASS(e, akgl_stage_2d_bsp_actoriter(actor->bsplistnode, &context));
|
||||
}
|
||||
curnode = curnode->parent;
|
||||
}
|
||||
// Release the old actor node, it will have been moved to a new one by now
|
||||
if ( tmp == actor->bsplistnode ) {
|
||||
// Odd ...
|
||||
SDL_Log("Expected actor %p to be moved to a different BSP node after moving, but it still has the same list node...\n", actor);
|
||||
} else {
|
||||
PASS(e, akgl_heap_release_list(tmp));
|
||||
}
|
||||
}
|
||||
SUCCEED_RETURN(e);
|
||||
}
|
||||
@@ -49,12 +49,12 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_text_rendertextat(TTF_Font *font, char *
|
||||
color);
|
||||
}
|
||||
FAIL_ZERO_RETURN(errctx, textsurf, AKERR_NULLPOINTER, "%s", SDL_GetError());
|
||||
texture = SDL_CreateTextureFromSurface(renderer.sdl_renderer, textsurf);
|
||||
texture = SDL_CreateTextureFromSurface(renderer->sdl_renderer, textsurf);
|
||||
FAIL_ZERO_RETURN(errctx, texture, AKERR_NULLPOINTER, "%s", SDL_GetError());
|
||||
dest.x = x;
|
||||
dest.y = y;
|
||||
SDL_GetTextureSize(texture, &dest.w, &dest.h);
|
||||
PASS(errctx, renderer.draw_texture(&renderer, texture, NULL, &dest, 0, NULL, SDL_FLIP_NONE));
|
||||
PASS(errctx, renderer->draw_texture(renderer, texture, NULL, &dest, 0, NULL, SDL_FLIP_NONE));
|
||||
SDL_DestroyTexture(texture);
|
||||
SDL_DestroySurface(textsurf);
|
||||
SUCCEED_RETURN(errctx);
|
||||
|
||||
206
src/tilemap.c
206
src/tilemap.c
@@ -64,15 +64,11 @@ akerr_ErrorContext *akgl_get_json_properties_string(json_t *obj, char *key, akgl
|
||||
PREPARE_ERROR(errctx);
|
||||
json_t *property;
|
||||
|
||||
ATTEMPT {
|
||||
CATCH(errctx, akgl_get_json_tilemap_property(obj, key, "string", &property));
|
||||
CATCH(errctx, akgl_heap_next_string(dest));
|
||||
CATCH(errctx, akgl_string_initialize(*dest, NULL));
|
||||
CATCH(errctx, akgl_get_json_string_value(property, "value", dest));
|
||||
} CLEANUP {
|
||||
} PROCESS(errctx) {
|
||||
} FINISH(errctx, true);
|
||||
|
||||
PASS(errctx, akgl_get_json_tilemap_property(obj, key, "string", &property));
|
||||
PASS(errctx, akgl_heap_next_string(dest));
|
||||
PASS(errctx, akgl_string_initialize(*dest, NULL));
|
||||
PASS(errctx, akgl_get_json_string_value(property, "value", dest));
|
||||
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
|
||||
@@ -80,12 +76,8 @@ akerr_ErrorContext *akgl_get_json_properties_integer(json_t *obj, char *key, int
|
||||
{
|
||||
PREPARE_ERROR(errctx);
|
||||
json_t *property = NULL;
|
||||
ATTEMPT {
|
||||
CATCH(errctx, akgl_get_json_tilemap_property(obj, key, "int", &property));
|
||||
CATCH(errctx, akgl_get_json_integer_value(property, "value", dest));
|
||||
} CLEANUP {
|
||||
} PROCESS(errctx) {
|
||||
} FINISH(errctx, true);
|
||||
PASS(errctx, akgl_get_json_tilemap_property(obj, key, "int", &property));
|
||||
PASS(errctx, akgl_get_json_integer_value(property, "value", dest));
|
||||
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
@@ -94,12 +86,8 @@ akerr_ErrorContext *akgl_get_json_properties_number(json_t *obj, char *key, floa
|
||||
{
|
||||
PREPARE_ERROR(errctx);
|
||||
json_t *property = NULL;
|
||||
ATTEMPT {
|
||||
CATCH(errctx, akgl_get_json_tilemap_property(obj, key, "number", &property));
|
||||
CATCH(errctx, akgl_get_json_number_value(property, "value", dest));
|
||||
} CLEANUP {
|
||||
} PROCESS(errctx) {
|
||||
} FINISH(errctx, true);
|
||||
PASS(errctx, akgl_get_json_tilemap_property(obj, key, "number", &property));
|
||||
PASS(errctx, akgl_get_json_number_value(property, "value", dest));
|
||||
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
@@ -108,12 +96,18 @@ akerr_ErrorContext *akgl_get_json_properties_float(json_t *obj, char *key, float
|
||||
{
|
||||
PREPARE_ERROR(errctx);
|
||||
json_t *property = NULL;
|
||||
ATTEMPT {
|
||||
CATCH(errctx, akgl_get_json_tilemap_property(obj, key, "float", &property));
|
||||
CATCH(errctx, akgl_get_json_number_value(property, "value", dest));
|
||||
} CLEANUP {
|
||||
} PROCESS(errctx) {
|
||||
} FINISH(errctx, true);
|
||||
PASS(errctx, akgl_get_json_tilemap_property(obj, key, "float", &property));
|
||||
PASS(errctx, akgl_get_json_number_value(property, "value", dest));
|
||||
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
|
||||
akerr_ErrorContext *akgl_get_json_properties_double(json_t *obj, char *key, double *dest)
|
||||
{
|
||||
PREPARE_ERROR(errctx);
|
||||
json_t *property = NULL;
|
||||
PASS(errctx, akgl_get_json_tilemap_property(obj, key, "float", &property));
|
||||
PASS(errctx, akgl_get_json_double_value(property, "value", dest));
|
||||
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
@@ -152,7 +146,7 @@ akerr_ErrorContext *akgl_tilemap_load_tilesets_each(json_t *tileset, akgl_Tilema
|
||||
} PROCESS(e) {
|
||||
} FINISH(e, true);
|
||||
|
||||
dest->tilesets[tsidx].texture = IMG_LoadTexture(renderer.sdl_renderer, (char *)&dest->tilesets[tsidx].imagefilename);
|
||||
dest->tilesets[tsidx].texture = IMG_LoadTexture(renderer->sdl_renderer, (char *)&dest->tilesets[tsidx].imagefilename);
|
||||
FAIL_ZERO_RETURN(e, dest->tilesets[tsidx].texture, AKERR_NULLPOINTER, "Failed loading tileset image : %s", SDL_GetError());
|
||||
|
||||
SUCCEED_RETURN(e);
|
||||
@@ -297,41 +291,36 @@ akerr_ErrorContext *akgl_tilemap_load_layer_objects(akgl_Tilemap *dest, json_t *
|
||||
FAIL_ZERO_RETURN(errctx, dest, AKERR_NULLPOINTER, "NULL destination tilemap reference");
|
||||
FAIL_ZERO_RETURN(errctx, root, AKERR_NULLPOINTER, "NULL tilemap root reference");
|
||||
|
||||
ATTEMPT {
|
||||
CATCH(errctx, akgl_get_json_array_value(root, "objects", &layerdata));
|
||||
len = json_array_size((json_t *)layerdata);
|
||||
curlayer = &dest->layers[layerid];
|
||||
for ( j = 0; j < len; j++ ) {
|
||||
CATCH(errctx, akgl_get_json_array_index_object((json_t *)layerdata, j, &layerdatavalue));
|
||||
curobj = &curlayer->objects[j];
|
||||
CATCH(errctx, akgl_get_json_string_value((json_t *)layerdatavalue, "name", &tmpstr));
|
||||
strncpy((char *)curobj->name, tmpstr->data, AKGL_ACTOR_MAX_NAME_LENGTH);
|
||||
CATCH(errctx, akgl_heap_release_string(tmpstr));
|
||||
CATCH(errctx, akgl_get_json_number_value((json_t *)layerdatavalue, "x", &curobj->x));
|
||||
CATCH(errctx, akgl_get_json_number_value((json_t *)layerdatavalue, "y", &curobj->y));
|
||||
CATCH(errctx, akgl_get_json_boolean_value((json_t *)layerdatavalue, "visible", &curobj->visible));
|
||||
|
||||
CATCH(errctx, akgl_get_json_string_value((json_t *)layerdatavalue, "type", &tmpstr));
|
||||
if ( strcmp(tmpstr->data, "actor") == 0 ) {
|
||||
CATCH(errctx, akgl_tilemap_load_layer_object_actor(curobj, layerdatavalue, layerid, dirname));
|
||||
} else if ( strcmp(tmpstr->data, "perspective") == 0 ) {
|
||||
curobj->visible = false;
|
||||
if ( strcmp((char *)curobj->name, "p_foreground") == 0 ) {
|
||||
dest->p_foreground_y = curobj->y;
|
||||
CATCH(errctx, akgl_get_json_integer_value((json_t *)layerdatavalue, "height", &dest->p_foreground_h));
|
||||
CATCH(errctx, akgl_get_json_properties_float((json_t *)layerdatavalue, "scale", &dest->p_foreground_scale));
|
||||
} else if ( strcmp((char *)curobj->name, "p_vanishing") == 0 ) {
|
||||
dest->p_vanishing_y = curobj->y;
|
||||
CATCH(errctx, akgl_get_json_integer_value((json_t *)layerdatavalue, "height", &dest->p_vanishing_h));
|
||||
CATCH(errctx, akgl_get_json_properties_float((json_t *)layerdatavalue, "scale", &dest->p_vanishing_scale));
|
||||
}
|
||||
}
|
||||
|
||||
layerdatavalue = NULL;
|
||||
}
|
||||
} CLEANUP {
|
||||
} PROCESS(errctx) {
|
||||
} FINISH(errctx, true);
|
||||
PASS(errctx, akgl_get_json_array_value(root, "objects", &layerdata));
|
||||
len = json_array_size((json_t *)layerdata);
|
||||
curlayer = &dest->layers[layerid];
|
||||
for ( j = 0; j < len; j++ ) {
|
||||
PASS(errctx, akgl_get_json_array_index_object((json_t *)layerdata, j, &layerdatavalue));
|
||||
curobj = &curlayer->objects[j];
|
||||
PASS(errctx, akgl_get_json_string_value((json_t *)layerdatavalue, "name", &tmpstr));
|
||||
strncpy((char *)curobj->name, tmpstr->data, AKGL_ACTOR_MAX_NAME_LENGTH);
|
||||
PASS(errctx, akgl_heap_release_string(tmpstr));
|
||||
PASS(errctx, akgl_get_json_number_value((json_t *)layerdatavalue, "x", &curobj->x));
|
||||
PASS(errctx, akgl_get_json_number_value((json_t *)layerdatavalue, "y", &curobj->y));
|
||||
PASS(errctx, akgl_get_json_boolean_value((json_t *)layerdatavalue, "visible", &curobj->visible));
|
||||
|
||||
PASS(errctx, akgl_get_json_string_value((json_t *)layerdatavalue, "type", &tmpstr));
|
||||
if ( strcmp(tmpstr->data, "actor") == 0 ) {
|
||||
PASS(errctx, akgl_tilemap_load_layer_object_actor(curobj, layerdatavalue, layerid, dirname));
|
||||
} else if ( strcmp(tmpstr->data, "perspective") == 0 ) {
|
||||
curobj->visible = false;
|
||||
if ( strcmp((char *)curobj->name, "p_foreground") == 0 ) {
|
||||
dest->p_foreground_y = curobj->y;
|
||||
PASS(errctx, akgl_get_json_integer_value((json_t *)layerdatavalue, "height", &dest->p_foreground_h));
|
||||
PASS(errctx, akgl_get_json_properties_float((json_t *)layerdatavalue, "scale", &dest->p_foreground_scale));
|
||||
} else if ( strcmp((char *)curobj->name, "p_vanishing") == 0 ) {
|
||||
dest->p_vanishing_y = curobj->y;
|
||||
PASS(errctx, akgl_get_json_integer_value((json_t *)layerdatavalue, "height", &dest->p_vanishing_h));
|
||||
PASS(errctx, akgl_get_json_properties_float((json_t *)layerdatavalue, "scale", &dest->p_vanishing_scale));
|
||||
}
|
||||
}
|
||||
layerdatavalue = NULL;
|
||||
}
|
||||
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
@@ -389,7 +378,7 @@ akerr_ErrorContext *akgl_tilemap_load_layer_image(akgl_Tilemap *dest, json_t *ro
|
||||
);
|
||||
RESTORE_GCC_WARNINGS
|
||||
|
||||
dest->layers[layerid].texture = IMG_LoadTexture(renderer.sdl_renderer, (char *)fpath->data);
|
||||
dest->layers[layerid].texture = IMG_LoadTexture(renderer->sdl_renderer, (char *)fpath->data);
|
||||
FAIL_ZERO_BREAK(errctx, dest->layers[layerid].texture, AKGL_ERR_SDL, "%s", SDL_GetError());
|
||||
dest->layers[layerid].width = dest->layers[layerid].texture->w;
|
||||
dest->layers[layerid].height = dest->layers[layerid].texture->h;
|
||||
@@ -451,6 +440,88 @@ akerr_ErrorContext *akgl_tilemap_load_layers(akgl_Tilemap *dest, json_t *root, a
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
|
||||
akerr_ErrorContext *akgl_tilemap_load_physics(akgl_Tilemap *dest, json_t *root)
|
||||
{
|
||||
PREPARE_ERROR(e);
|
||||
json_t *props = NULL;
|
||||
akgl_String *tmpval = NULL;
|
||||
double defzero = 0.0;
|
||||
|
||||
ATTEMPT {
|
||||
CATCH(e, akgl_heap_next_string(&tmpval));
|
||||
CATCH(e, akgl_get_json_array_value((json_t *)root, "properties", &props));
|
||||
} CLEANUP {
|
||||
IGNORE(akgl_heap_release_string(tmpval));
|
||||
} PROCESS(e) {
|
||||
} HANDLE(e, AKERR_KEY) {
|
||||
// Map has no properties, do nothing
|
||||
SDL_Log("Map has no properties");
|
||||
SUCCEED_RETURN(e);
|
||||
} FINISH(e, true);
|
||||
|
||||
ATTEMPT {
|
||||
CATCH(e, akgl_heap_next_string(&tmpval));
|
||||
CATCH(e, akgl_get_json_properties_string(
|
||||
root,
|
||||
"physics.model",
|
||||
&tmpval
|
||||
)
|
||||
);
|
||||
PASS(e, akgl_physics_factory(&dest->physics, tmpval));
|
||||
dest->use_own_physics = true;
|
||||
|
||||
CATCH(e, akgl_get_json_with_default(
|
||||
akgl_get_json_properties_double(
|
||||
root, "physics.gravity.x", &dest->physics.gravity_x
|
||||
),
|
||||
(void *)&defzero,
|
||||
(void *)&dest->physics.gravity_x,
|
||||
sizeof(double)));
|
||||
CATCH(e, akgl_get_json_with_default(
|
||||
akgl_get_json_properties_double(
|
||||
root, "physics.gravity.y", &dest->physics.gravity_y
|
||||
),
|
||||
(void *)&defzero,
|
||||
(void *)&dest->physics.gravity_y,
|
||||
sizeof(double)));
|
||||
CATCH(e, akgl_get_json_with_default(
|
||||
akgl_get_json_properties_double(
|
||||
root, "physics.gravity.z", &dest->physics.gravity_z
|
||||
),
|
||||
(void *)&defzero,
|
||||
(void *)&dest->physics.gravity_z,
|
||||
sizeof(double)));
|
||||
CATCH(e, akgl_get_json_with_default(
|
||||
akgl_get_json_properties_double(
|
||||
root, "physics.drag.x", &dest->physics.drag_x
|
||||
),
|
||||
(void *)&defzero,
|
||||
(void *)&dest->physics.drag_x,
|
||||
sizeof(double)));
|
||||
CATCH(e, akgl_get_json_with_default(
|
||||
akgl_get_json_properties_double(
|
||||
root, "physics.drag.y", &dest->physics.drag_y
|
||||
),
|
||||
(void *)&defzero,
|
||||
(void *)&dest->physics.drag_y,
|
||||
sizeof(double)));
|
||||
CATCH(e, akgl_get_json_with_default(
|
||||
akgl_get_json_properties_double(
|
||||
root, "physics.drag.z", &dest->physics.drag_z
|
||||
),
|
||||
(void *)&defzero,
|
||||
(void *)&dest->physics.drag_z,
|
||||
sizeof(double)));
|
||||
} CLEANUP {
|
||||
IGNORE(akgl_heap_release_string(tmpval));
|
||||
} PROCESS(e) {
|
||||
} HANDLE(e, AKERR_KEY) {
|
||||
SDL_Log("Map uses game physics");
|
||||
} FINISH(e, true);
|
||||
|
||||
SUCCEED_RETURN(e);
|
||||
}
|
||||
|
||||
akerr_ErrorContext *akgl_tilemap_load(char *fname, akgl_Tilemap *dest)
|
||||
{
|
||||
PREPARE_ERROR(errctx);
|
||||
@@ -484,6 +555,7 @@ akerr_ErrorContext *akgl_tilemap_load(char *fname, akgl_Tilemap *dest)
|
||||
error.line,
|
||||
error.text
|
||||
);
|
||||
CATCH(errctx, akgl_tilemap_load_physics(dest, json));
|
||||
CATCH(errctx, akgl_get_json_integer_value((json_t *)json, "tileheight", &dest->tileheight));
|
||||
CATCH(errctx, akgl_get_json_integer_value((json_t *)json, "tilewidth", &dest->tilewidth));
|
||||
CATCH(errctx, akgl_get_json_integer_value((json_t *)json, "height", &dest->height));
|
||||
@@ -573,7 +645,7 @@ akerr_ErrorContext *akgl_tilemap_draw(akgl_Tilemap *map, SDL_FRect *viewport, in
|
||||
src.h = map->layers[layeridx].height;
|
||||
dest.w = map->layers[layeridx].width;
|
||||
dest.h = map->layers[layeridx].height;
|
||||
PASS(errctx, renderer.draw_texture(&renderer, map->layers[layeridx].texture, &src, &dest, 0, NULL, SDL_FLIP_NONE));
|
||||
PASS(errctx, renderer->draw_texture(renderer, map->layers[layeridx].texture, &src, &dest, 0, NULL, SDL_FLIP_NONE));
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
|
||||
@@ -628,7 +700,7 @@ akerr_ErrorContext *akgl_tilemap_draw(akgl_Tilemap *map, SDL_FRect *viewport, in
|
||||
dest.y,
|
||||
dest.w,
|
||||
dest.h);*/
|
||||
PASS(errctx, renderer.draw_texture(&renderer, map->tilesets[tilesetidx].texture, &src, &dest, 0, NULL, SDL_FLIP_NONE));
|
||||
PASS(errctx, renderer->draw_texture(renderer, map->tilesets[tilesetidx].texture, &src, &dest, 0, NULL, SDL_FLIP_NONE));
|
||||
}
|
||||
}
|
||||
dest.x += map->tilewidth;
|
||||
@@ -683,7 +755,7 @@ akerr_ErrorContext *akgl_tilemap_draw_tileset(akgl_Tilemap *map, int tilesetidx)
|
||||
dest.y,
|
||||
dest.w,
|
||||
dest.h);*/
|
||||
PASS(errctx, renderer.draw_texture(&renderer, map->tilesets[tilesetidx].texture, &src, &dest, 0, NULL, SDL_FLIP_NONE));
|
||||
PASS(errctx, renderer->draw_texture(renderer, map->tilesets[tilesetidx].texture, &src, &dest, 0, NULL, SDL_FLIP_NONE));
|
||||
}
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
|
||||
12
src/util.c
12
src/util.c
@@ -202,9 +202,9 @@ akerr_ErrorContext *akgl_render_and_compare(SDL_Texture *t1, SDL_Texture *t2, in
|
||||
FAIL_ZERO_BREAK(errctx, t2, AKERR_NULLPOINTER, "NULL texture");
|
||||
|
||||
CATCH(errctx, akgl_heap_next_string(&tmpstring));
|
||||
SDL_RenderClear(renderer.sdl_renderer);
|
||||
CATCH(errctx, renderer.draw_texture(&renderer, t1, &src, &dest, 0, NULL, SDL_FLIP_NONE));
|
||||
s1 = SDL_RenderReadPixels(renderer.sdl_renderer, &read);
|
||||
SDL_RenderClear(renderer->sdl_renderer);
|
||||
CATCH(errctx, renderer->draw_texture(renderer, t1, &src, &dest, 0, NULL, SDL_FLIP_NONE));
|
||||
s1 = SDL_RenderReadPixels(renderer->sdl_renderer, &read);
|
||||
FAIL_ZERO_BREAK(errctx, s1, AKGL_ERR_SDL, "Failed to read pixels from renderer");
|
||||
|
||||
if ( writeout != NULL ) {
|
||||
@@ -218,10 +218,10 @@ akerr_ErrorContext *akgl_render_and_compare(SDL_Texture *t1, SDL_Texture *t2, in
|
||||
SDL_GetError());
|
||||
}
|
||||
|
||||
SDL_RenderClear(renderer.sdl_renderer);
|
||||
SDL_RenderClear(renderer->sdl_renderer);
|
||||
|
||||
CATCH(errctx, renderer.draw_texture(&renderer, t1, &src, &dest, 0, NULL, SDL_FLIP_NONE));
|
||||
s2 = SDL_RenderReadPixels(renderer.sdl_renderer, &read);
|
||||
CATCH(errctx, renderer->draw_texture(renderer, t1, &src, &dest, 0, NULL, SDL_FLIP_NONE));
|
||||
s2 = SDL_RenderReadPixels(renderer->sdl_renderer, &read);
|
||||
FAIL_ZERO_BREAK(errctx, s2, AKGL_ERR_SDL, "Failed to read pixels from renderer");
|
||||
|
||||
CATCH(errctx, akgl_compare_sdl_surfaces(s1, s2));
|
||||
|
||||
Reference in New Issue
Block a user