From c78bc5e88bef99afba8959117d49c31b798369fb Mon Sep 17 00:00:00 2001 From: Alvie Rahman Date: Mon, 6 Jun 2022 22:19:34 +0100 Subject: [PATCH] first commit - a kind of working thingy --- .gitignore | 2 + .gitmodules | 3 + Makefile | 60 +++++++++++++ gbdk-2020 | 1 + readme.md | 11 +++ res/map.c | 65 ++++++++++++++ res/map.h | 27 ++++++ res/sprites.c | 52 +++++++++++ res/sprites.gbr | Bin 0 -> 10069 bytes res/sprites.h | 31 +++++++ res/test.gbm | Bin 0 -> 2716 bytes res/tilemap.gbm | Bin 0 -> 2396 bytes res/tiles.c | 76 ++++++++++++++++ res/tiles.gbr | Bin 0 -> 10347 bytes res/tiles.h | 31 +++++++ src/constants.h | 21 +++++ src/flags.h | 39 +++++++++ src/main.c | 224 ++++++++++++++++++++++++++++++++++++++++++++++++ src/vec.c | 9 ++ 19 files changed, 652 insertions(+) create mode 100644 .gitignore create mode 100644 .gitmodules create mode 100644 Makefile create mode 160000 gbdk-2020 create mode 100644 readme.md create mode 100644 res/map.c create mode 100644 res/map.h create mode 100644 res/sprites.c create mode 100644 res/sprites.gbr create mode 100644 res/sprites.h create mode 100644 res/test.gbm create mode 100644 res/tilemap.gbm create mode 100644 res/tiles.c create mode 100644 res/tiles.gbr create mode 100644 res/tiles.h create mode 100644 src/constants.h create mode 100644 src/flags.h create mode 100644 src/main.c create mode 100644 src/vec.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0c333d2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +compile.bat +obj diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..6fdf0fc --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "gbdk-2020"] + path = gbdk-2020 + url = https://github.com/gbdk-2020/gbdk-2020.git diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..f172daa --- /dev/null +++ b/Makefile @@ -0,0 +1,60 @@ +# +# A Makefile that compiles all .c and .s files in "src" and "res" +# subdirectories and places the output in a "obj" subdirectory +# + +# If you move this project you can change the directory +# to match your GBDK root directory (ex: GBDK_HOME = "C:/GBDK/" +GBDK_HOME = ./gbdk-2020/ + +LCC = $(GBDK_HOME)bin/lcc + +# You can set flags for LCC here +# For example, you can uncomment the line below to turn on debug output +# LCCFLAGS = -debug + +# You can set the name of the .gb ROM file here +PROJECTNAME = untitled2dshooter + +SRCDIR = src +OBJDIR = obj +RESDIR = res +BINS = $(OBJDIR)/$(PROJECTNAME).gb +CSOURCES = $(foreach dir,$(SRCDIR),$(notdir $(wildcard $(dir)/*.c))) $(foreach dir,$(RESDIR),$(notdir $(wildcard $(dir)/*.c))) +ASMSOURCES = $(foreach dir,$(SRCDIR),$(notdir $(wildcard $(dir)/*.s))) +OBJS = $(CSOURCES:%.c=$(OBJDIR)/%.o) $(ASMSOURCES:%.s=$(OBJDIR)/%.o) + +all: prepare $(BINS) + +compile.bat: Makefile + @echo "REM Automatically generated from Makefile" > compile.bat + @make -sn | sed y/\\//\\\\/ | grep -v make >> compile.bat + +# Compile .c files in "src/" to .o object files +$(OBJDIR)/%.o: $(SRCDIR)/%.c + $(LCC) $(LCCFLAGS) -c -o $@ $< + +# Compile .c files in "res/" to .o object files +$(OBJDIR)/%.o: $(RESDIR)/%.c + $(LCC) $(LCCFLAGS) -c -o $@ $< + +# Compile .s assembly files in "src/" to .o object files +$(OBJDIR)/%.o: $(SRCDIR)/%.s + $(LCC) $(LCCFLAGS) -c -o $@ $< + +# If needed, compile .c files i n"src/" to .s assembly files +# (not required if .c is compiled directly to .o) +$(OBJDIR)/%.s: $(SRCDIR)/%.c + $(LCC) $(LCCFLAGS) -S -o $@ $< + +# Link the compiled object files into a .gb ROM file +$(BINS): $(OBJS) + $(LCC) $(LCCFLAGS) -o $(BINS) $(OBJS) + +prepare: + mkdir -p $(OBJDIR) + +clean: +# rm -f *.gb *.ihx *.cdb *.adb *.noi *.map + rm -f $(OBJDIR)/*.* + diff --git a/gbdk-2020 b/gbdk-2020 new file mode 160000 index 0000000..ebbc0b0 --- /dev/null +++ b/gbdk-2020 @@ -0,0 +1 @@ +Subproject commit ebbc0b0ed11267182c922fcbf87da915b9e90526 diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..d7527b1 --- /dev/null +++ b/readme.md @@ -0,0 +1,11 @@ +# untitled2dshooter + +an untitled 2d multiplayer shooter for the gameboy + +## compile + +``` +make all +``` + +the gameboy rom will be output to `obj/untitled2dshooter.gb` diff --git a/res/map.c b/res/map.c new file mode 100644 index 0000000..f4bbfbd --- /dev/null +++ b/res/map.c @@ -0,0 +1,65 @@ +/* + + MAP.C + + Map Source File. + + Info: + Section : + Bank : 0 + Map size : 20 x 18 + Tile set : Z:\home\alvie\d\p\wordboy\res\tiles.gbr + Plane count : 1 plane (8 bits) + Plane order : Tiles are continues + Tile offset : 0 + Split data : No + + This file was generated by GBMB v1.8 + +*/ + +#define mapWidth 20 +#define mapHeight 18 +#define mapBank 0 + +unsigned char map[] = +{ + 0x09,0x02,0x02,0x02,0x02,0x02,0x02,0x08,0x00,0x00, + 0x00,0x07,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x0A, + 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03, + 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03, + 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03, + 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03, + 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03, + 0x04,0x00,0x00,0x0D,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03, + 0x04,0x00,0x00,0x11,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03, + 0x04,0x00,0x00,0x03,0x0F,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03, + 0x04,0x00,0x00,0x11,0x00,0x00,0x0E,0x12,0x12,0x12, + 0x12,0x12,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x03, + 0x04,0x00,0x00,0x11,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03, + 0x04,0x00,0x00,0x11,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x0E,0x12,0x12,0x0F,0x00,0x00,0x00,0x03, + 0x04,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03, + 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x01,0x0B, + 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x13,0x13, + 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0B,0x13,0x13, + 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x05,0x0B,0x13,0x13,0x13, + 0x0C,0x01,0x01,0x01,0x01,0x01,0x01,0x06,0x00,0x00, + 0x00,0x05,0x01,0x01,0x01,0x0B,0x13,0x13,0x13,0x13 +}; + +/* End of MAP.C */ diff --git a/res/map.h b/res/map.h new file mode 100644 index 0000000..16f1362 --- /dev/null +++ b/res/map.h @@ -0,0 +1,27 @@ +/* + + MAP.H + + Map Include File. + + Info: + Section : + Bank : 0 + Map size : 20 x 18 + Tile set : Z:\home\alvie\d\p\wordboy\res\tiles.gbr + Plane count : 1 plane (8 bits) + Plane order : Tiles are continues + Tile offset : 0 + Split data : No + + This file was generated by GBMB v1.8 + +*/ + +#define mapWidth 20 +#define mapHeight 18 +#define mapBank 0 + +extern unsigned char map[]; + +/* End of MAP.H */ diff --git a/res/sprites.c b/res/sprites.c new file mode 100644 index 0000000..82adceb --- /dev/null +++ b/res/sprites.c @@ -0,0 +1,52 @@ +/* + + SPRITES.C + + Tile Source File. + + Info: + Form : All tiles as one unit. + Format : Gameboy 4 color. + Compression : None. + Counter : None. + Tile size : 8 x 8 + Tiles : 0 to 10 + + Palette colors : None. + SGB Palette : None. + CGB Palette : None. + + Convert to metatiles : No. + + This file was generated by GBTD v2.2 + +*/ + +/* Start of tile array. */ +unsigned char sprites[] = +{ + 0xF7,0x08,0xED,0x12,0xFE,0x11,0xFF,0x38, + 0xFE,0x39,0xFE,0x39,0xFF,0x7E,0xFF,0x6E, + 0xFF,0x00,0xC3,0x42,0x81,0x00,0x81,0x00, + 0x81,0x00,0x81,0x00,0xC3,0x42,0xFF,0x00, + 0xC3,0xC3,0xDB,0xDB,0x3C,0x3C,0x7E,0x7E, + 0x7E,0x7E,0x3C,0x3C,0xDB,0xDB,0xC3,0xC3, + 0x43,0xC3,0xDB,0xDB,0x3C,0x3C,0x7E,0x7E, + 0x7E,0x7E,0x3C,0x3C,0xDB,0xDB,0xC3,0xC3, + 0xC2,0xC3,0xDB,0xDB,0x3C,0x3C,0x7E,0x7E, + 0x7E,0x7E,0x3C,0x3C,0xDB,0xDB,0xC3,0xC3, + 0xC3,0xC3,0xDB,0xDB,0x3C,0x3C,0x7E,0x7E, + 0x7E,0x7E,0x3C,0x3C,0xDB,0xDB,0x43,0xC3, + 0xC3,0xC3,0xDB,0xDB,0x3C,0x3C,0x7E,0x7E, + 0x7E,0x7E,0x3C,0x3C,0xDB,0xDB,0xC2,0xC3, + 0x42,0xC3,0xDB,0xDB,0x3C,0x3C,0x7E,0x7E, + 0x7E,0x7E,0x3C,0x3C,0xDB,0xDB,0xC3,0xC3, + 0xC2,0xC3,0xDB,0xDB,0x3C,0x3C,0x7E,0x7E, + 0x7E,0x7E,0x3C,0x3C,0xDB,0xDB,0xC2,0xC3, + 0xC3,0xC3,0xDB,0xDB,0x3C,0x3C,0x7E,0x7E, + 0x7E,0x7E,0x3C,0x3C,0xDB,0xDB,0x42,0xC3, + 0x43,0xC3,0xDB,0xDB,0x3C,0x3C,0x7E,0x7E, + 0x7E,0x7E,0x3C,0x3C,0xDB,0xDB,0x43,0xC3 +}; + +/* End of SPRITES.C */ diff --git a/res/sprites.gbr b/res/sprites.gbr new file mode 100644 index 0000000000000000000000000000000000000000..368fb5d753a8d6ace8c95d7ce0b5fadd0abc2270 GIT binary patch literal 10069 zcmeI2u};G<5QZ;yS}G*E@B$fO3DB)fs6r|m3la-UDHc>p+Nx<)SfFpf3-A~$%)A3L zZ@|C=l}AhTik3M?*;&HjlX6qHRrvX=%kaF=+I=H%dQz< z+_qX=g9A8wKZT=SYWAb?cpSG|nMqr5*9>=VulngIxyU8>#JQ>M2dD@O~E3g*|$4IE-)y4ffUV|~U zWWL)+`F*V+Jqouko#F56_-%f!ZfAxDbU7auKO}W=yNGHd&|0~DmaTu$e9H5++0uSk zzpp#TVUc`xrwXJA0U;m+gn$qb0zyCt2mv7=1cZPP5CTF#2nYcoAOwVf5D)@FKnMr{ zAs__)I{^&}HW31Tx5rQT0V#ZNgAg=4^HkO!bcQC2+kZq$(qAD5!(r z;%^Xfbn*`fX9-o|>kjQDxn1)rI zMU!iRN!199W#Wk#OF55!WE_@9>^PC6&O!mrG>uR&n9XM8MK#TIRbFOhFsB)M=9|wZ z)Ttv!pKWLIBRYH>qyuo9{b)XUfi&2@?+LD6OSe8RdBE5K z_ASXv5%`$k=y~VM`SQT>80%mnPnP9mYM^j*A5kqo@PY>PP{TviK!hvTLil_43jI8| zsmM95Zfn|rtCwP4Xi?|bOPlgyg*|^9<|X>6X6xkcE7BnRc;1Rt#dUX@$V5GoD%?j<8HK7q52U+>tVCC%h~U-(x> KYB`c{Zh8ZWGMYaC literal 0 HcmV?d00001 diff --git a/res/tilemap.gbm b/res/tilemap.gbm new file mode 100644 index 0000000000000000000000000000000000000000..36a8e1b2961f9f9712a84fc960c4cff8c4a53070 GIT binary patch literal 2396 zcmd^A&1(}u6o0#IJ{q-ZtB_+3Mewq*x3b=PX%Jg0c#^$rn#B!d&5~>lwNgUq!FziU zgi^?*r}kj~h9de8c+`t{6cu_A*5BKiSw?Mf6R?*)=IzY9uiwj?nU{t62eY;1dy9|m z8>Fa&<$@b{_4Zn2(G4r}tIbx!>nQcP%(K><#HqCd&#w4U6x!8luh+9y+^!e6)>AL4 zZunua`k!+X)iFucXGbm0r4FZq+<sixt8cyi++MNc@&gpnvCu+95 zuJxqep@X##N#@}puVutj zX1cGE{d>+4zottg-De<9Cu7*R08k)~;Hx{r{c@5#^4ABqDn;Vg32lnVxT2Sg<8neN zNyu_|*?-FNl>19oK<^TEGw}a}<$K;5_;9mAZ17@Fj;v}XQs)5_s6DEL$RyKKvXNkODY3Cq?+3xvxEJ;Fn}ltoXP z&h#0T5iX^4B?_vjnO5qc#N-2lyoI0Ie&)}YiIYU;Ut&t6qG+n+r^HNm$%6~ek5CaK z5idHkZ9I|Eq!gtnvVk-iqrZ3IGNe*g74>PXtV)h7=FQd@&0}Dcr|K_|pH?TfD0TzA z>Ca?zc6|Cu!A#NfC(@GCcp%k025#WOn?b60Vco%m;e)C z0!-ka6R^O9E!+eCnUDYSix0q<8Wg~Scbe+sB?jMVEp4loxJBV>a>t0yH z%{-x(t}IN<=I(fu6*o{=QIN;$7$2XzP<^X`Jve~%s+0S;kb6aa$73i$nP}L#pNL*? j`3jVxvY=8B@5o5G*sdr6egjtY;KOad7>(y+Xl#B1ThM)1 literal 0 HcmV?d00001 diff --git a/res/tiles.h b/res/tiles.h new file mode 100644 index 0000000..ff45776 --- /dev/null +++ b/res/tiles.h @@ -0,0 +1,31 @@ +/* + + TILES.H + + Include File. + + Info: + Form : All tiles as one unit. + Format : Gameboy 4 color. + Compression : None. + Counter : None. + Tile size : 8 x 8 + Tiles : 0 to 22 + + Palette colors : None. + SGB Palette : None. + CGB Palette : None. + + Convert to metatiles : No. + + This file was generated by GBTD v2.2 + +*/ + + +/* Bank of tiles. */ +#define tilesBank 0 +/* Start of tile array. */ +extern unsigned char tiles[]; + +/* End of TILES.H */ diff --git a/src/constants.h b/src/constants.h new file mode 100644 index 0000000..08c62b3 --- /dev/null +++ b/src/constants.h @@ -0,0 +1,21 @@ +#ifndef CONSTANTS_LOADED +#define CONSTANTS_LOADED + +#define GRAV_ACC 1 +#define TERM_VELY 3 +#define TERM_VELX 2 +#define TERM_VELY_DIVISOR 3 +#define TERM_VELX_DIVISOR 3 + +#define JUMP_VEL 4 +#define JUMP_TIMEOUT_FRAMES 18 + +#define DASH_VELL 7 +#define DASH_VELD 5 +#define DASH_TIMEOUT_FRAMES 30 + +#define SPRITE_WIDTH 8 +#define SPRITE_HEIGHT 8 +#define PIXELS_PER_TILE 8 +#define TILES_PER_ROW 20 +#endif diff --git a/src/flags.h b/src/flags.h new file mode 100644 index 0000000..585ee16 --- /dev/null +++ b/src/flags.h @@ -0,0 +1,39 @@ +#define SPRITE_PROP_BEHIND 0b10000000 +#define SPRITE_PROP_VERTICAL_FLIP 0b01000000 +#define SPRITE_PROP_HORIZONTAL_FLIP 0b00100000 + +#define COLLISION_TOP_LEFT 0b10000000 +#define COLLISION_TOP_RIGHT 0b01000000 +#define COLLISION_BOTTOM_LEFT 0b00100000 +#define COLLISION_BOTTOM_RIGHT 0b00010000 + + +// Sprite Collision flags used by uint8_t collision(uint8_t, uint8_t, uint8_t, uint8_t) + +#define SC_TL 0b10000000 +#define SC_TR 0b01000000 +#define SC_BL 0b00100000 +#define SC_BR 0b00010000 +#define SC_LT 0b00001000 +#define SC_LB 0b00000100 +#define SC_RT 0b00000010 +#define SC_RB 0b00000001 + +#define SC_ITL 0b1000 +#define SC_ITR 0b0100 +#define SC_IBL 0b0010 +#define SC_IBR 0b0001 + +/* Sprite Collision point diagram: + * x TL LT x + * ------------ + * LT x|x ITL ITR x|x RT + * | | + * | | + * | | + * | | + * | | + * LB x|x IBL IBR x|x RB + * ------------ + * x TL LT x + */ diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..e5ca645 --- /dev/null +++ b/src/main.c @@ -0,0 +1,224 @@ +#include +#include +#include "../res/tiles.h" +#include "../res/map.h" +#include"../res/sprites.h" +#include "./flags.h" +#include "./constants.h" +#include "./vec.c" + +int getTileIndexByCoord(unsigned int x, unsigned int y) +{ + return ((y / PIXELS_PER_TILE) * 20) + (x / PIXELS_PER_TILE); +} + +// check for external collisions (if rectangle is at least touchign something) +unsigned int collision(unsigned char map[], struct UVec *sprite_pos, struct UVec *sprite_size) +{ + unsigned int rv = 0; + struct UVec itl, itr, ibl, ibr; + + itl.x = sprite_pos->x-8; itl.y = sprite_pos->y-16; + itr.x = sprite_pos->x-1; itr.y = sprite_pos->y-16; + ibl.x = sprite_pos->x-8; ibl.y = sprite_pos->y-9; + ibr.x = sprite_pos->x-1; ibr.y = sprite_pos->y-9; + + // check if corners are in a non 0 tile + if (map[getTileIndexByCoord(itl.x, itl.y-1)]) rv = rv | SC_TL; + if (map[getTileIndexByCoord(itr.x, itr.y-1)]) rv = rv | SC_TR; + + if (map[getTileIndexByCoord(ibl.x, ibl.y+1)]) rv = rv | SC_BL; + if (map[getTileIndexByCoord(ibr.x, ibr.y+1)]) rv = rv | SC_BR; + + if (map[getTileIndexByCoord(itl.x-1, itl.y)]) rv = rv | SC_LT; + if (map[getTileIndexByCoord(ibl.x-1, ibl.y)]) rv = rv | SC_LB; + + if (map[getTileIndexByCoord(itr.x+1, itr.y)]) rv = rv | SC_RT; + if (map[getTileIndexByCoord(ibr.x+1, ibr.y)]) rv = rv | SC_RB; + + return rv; +} + + +// calculate internal collisions from external collisions +unsigned int icollision(unsigned char map[], struct UVec *sprite_pos, struct UVec *sprite_size) +{ + unsigned int c, rv = 0; + struct UVec itl, itr, ibl, ibr; + + itl.x = sprite_pos->x-8; itl.y = sprite_pos->y-16; + itr.x = sprite_pos->x-1; itr.y = sprite_pos->y-16; + ibl.x = sprite_pos->x-8; ibl.y = sprite_pos->y-9; + ibr.x = sprite_pos->x-1; ibr.y = sprite_pos->y-9; + + if (map[getTileIndexByCoord(itl.x, itl.y)]) rv = rv | SC_ITL; + if (map[getTileIndexByCoord(itr.x, itr.y)]) rv = rv | SC_ITR; + if (map[getTileIndexByCoord(ibl.x, ibl.y)]) rv = rv | SC_IBL; + if (map[getTileIndexByCoord(ibr.x, ibr.y)]) rv = rv | SC_IBR; + + return rv; +} + + +void init_gfx() +{ + // Load Background tiles and then map + set_bkg_data(0, 23, tiles); + set_bkg_tiles(0, 0, mapWidth, mapHeight, map); + + set_sprite_data(0, 11, sprites); + set_sprite_tile(0, 2); + set_sprite_prop(0, 0); + + // Turn the background map on to make it visible + SHOW_BKG; + SHOW_SPRITES; +} + +void main(void) +{ + unsigned int c, search_found, frames_since_last_jump, frames_since_last_dash, fc = 0; + int xsearch, ysearch; + struct UVec sprite_pos, search_pos, sprite_size; + struct Vec velocity, acceleration; + + init_gfx(); + + sprite_pos.x = 72; + sprite_pos.y = 35; + sprite_size.x = 8; + sprite_size.y = 8; + frames_since_last_jump = JUMP_TIMEOUT_FRAMES; + frames_since_last_dash = DASH_TIMEOUT_FRAMES; + velocity.x = 0; + velocity.y = 0; + acceleration.x = 0; + acceleration.y = 0; + + move_sprite(0, sprite_pos.x, sprite_pos.y); + + // Loop forever + while(1) { + // the gameboy simulates physics too quickly to have good control over the speeds of things + // so draw them less often and move them more + if (frames_since_last_jump <= JUMP_TIMEOUT_FRAMES) frames_since_last_jump++; + if (frames_since_last_dash <= DASH_TIMEOUT_FRAMES) frames_since_last_dash++; + + if (++fc % 2 == 0) { + velocity.y += GRAV_ACC; + fc = 0; + } + + // player move left/right + if ((joypad() & J_RIGHT) && (velocity.x < TERM_VELX)) acceleration.x = 1; + else if ((joypad() & J_LEFT) && (velocity.x > -TERM_VELX)) acceleration.x = -1; + else acceleration.x = -velocity.x/abs(velocity.x); + velocity.x += acceleration.x; + + // player dash + if ((joypad() & J_B) && (frames_since_last_dash > DASH_TIMEOUT_FRAMES)) { + int frames_since_last_dash_copy = frames_since_last_dash; + frames_since_last_dash = 0; + + if ((joypad() & J_LEFT) && !(joypad() & (J_UP | J_RIGHT | J_DOWN))) { + velocity.x = -DASH_VELL; + } else if ((joypad() & J_RIGHT) && !(joypad() & (J_UP | J_LEFT | J_DOWN))) { + velocity.x = DASH_VELL; + } else if ((joypad() & J_UP) && !(joypad() & (J_RIGHT | J_LEFT | J_DOWN))) { + velocity.y = -DASH_VELL; + } else if ((joypad() & J_DOWN) && !(joypad() & (J_UP | J_LEFT | J_RIGHT))) { + velocity.y = DASH_VELL; + } else if ((joypad() & J_RIGHT) && (joypad() & J_UP)) { + velocity.x = DASH_VELD; + velocity.y = -DASH_VELD; + } else if ((joypad() & J_LEFT) && (joypad() & J_UP)) { + velocity.x = -DASH_VELD; + velocity.y = -DASH_VELD; + } else if ((joypad() & J_LEFT) && (joypad() & J_DOWN)) { + velocity.x = -DASH_VELD; + velocity.y = DASH_VELD; + } else if ((joypad() & J_RIGHT) && (joypad() & J_DOWN)) { + velocity.x = DASH_VELD; + velocity.y = DASH_VELD; + } else { + // if player doesn't hold the right buttons to dash, don't dash and set the + // frames_since_last_dash counter back to what it was before + frames_since_last_dash = frames_since_last_dash_copy; + } + } + + // slow down sprite in kind of realistic way + // (in real life i think it's drag is proportional to velocity square but not + // sure if that is worth the compute yet) + if (velocity.y > TERM_VELY) velocity.y -= (abs(velocity.y)-TERM_VELY)/TERM_VELY_DIVISOR; + if (velocity.y < -TERM_VELY) velocity.y += (abs(velocity.y)-TERM_VELY)/TERM_VELY_DIVISOR; + if (velocity.x > TERM_VELX) velocity.x -= (abs(velocity.x)-TERM_VELX)/TERM_VELX_DIVISOR; + if (velocity.x < -TERM_VELX) velocity.x += (abs(velocity.x)-TERM_VELX)/TERM_VELX_DIVISOR; + + // don't let player move in a direction which they are already touching something + if (((c & SC_TL) | (c & SC_TR)) && (velocity.y < 0)) { velocity.y = 0; } + if (((c & SC_BL) | (c & SC_BR)) && (velocity.y > 0)) { + // player jump + if ((joypad() & J_A) && (frames_since_last_jump > JUMP_TIMEOUT_FRAMES)) { + velocity.y = -JUMP_VEL; + frames_since_last_jump = 0; + } + else velocity.y = 0; + } + if (((c & SC_RT) | (c & SC_RB)) && (velocity.x > 0)) { velocity.x = 0; } + if (((c & SC_LT) | (c & SC_LB)) && (velocity.x < 0)) { velocity.x = 0; } + + sprite_pos.x += velocity.x; + sprite_pos.y += velocity.y; + + c = collision(map, &sprite_pos, &sprite_size); + + // move player out of tiles by brute force searching :eyes: + // TODO this is really stupid and bad and i think it will have to be changed when there + // are more players moving around + search_found = 0; + for (ysearch = 0; ysearch <= SPRITE_HEIGHT; ysearch++) { + for (xsearch = 0; xsearch <= SPRITE_WIDTH; xsearch++) { + search_pos.x = sprite_pos.x + xsearch; + search_pos.y = sprite_pos.y + ysearch; + if(icollision(map, &search_pos, &sprite_size) == 0) { + sprite_pos.x = search_pos.x; + sprite_pos.y = search_pos.y; + search_found = 1; + break; + } + search_pos.x = sprite_pos.x - xsearch; + search_pos.y = sprite_pos.y + ysearch; + if(icollision(map, &search_pos, &sprite_size) == 0) { + sprite_pos.x = search_pos.x; + sprite_pos.y = search_pos.y; + search_found = 1; + break; + } + search_pos.x = sprite_pos.x - xsearch; + search_pos.y = sprite_pos.y - ysearch; + if(icollision(map, &search_pos, &sprite_size) == 0) { + sprite_pos.x = search_pos.x; + sprite_pos.y = search_pos.y; + search_found = 1; + break; + } + search_pos.x = sprite_pos.x + xsearch; + search_pos.y = sprite_pos.y - ysearch; + if(icollision(map, &search_pos, &sprite_size) == 0) { + sprite_pos.x = search_pos.x; + sprite_pos.y = search_pos.y; + search_found = 1; + break; + } + } + if (search_found) break; + } + + // finally move the sprite + move_sprite(0, sprite_pos.x, sprite_pos.y); + + // Done processing, yield CPU and wait for start of next frame + wait_vbl_done(); + } +} diff --git a/src/vec.c b/src/vec.c new file mode 100644 index 0000000..ac662ce --- /dev/null +++ b/src/vec.c @@ -0,0 +1,9 @@ +struct UVec { + unsigned int x; + unsigned int y; +}; + +struct Vec { + int x; + int y; +};