diff --git a/CMakeLists.txt b/CMakeLists.txt index 4bb84db..4b318e9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,14 @@ include_directories(inc) set(SOURCES src/main.c + src/player.c + src/level.c + src/bullet.c + src/attack.c + src/sandbag.c + src/tools.c + src/particle.c + src/overlay.c ) set(ASSETS @@ -22,5 +30,5 @@ add_executable(thyaddin ${SOURCES} ${ASSETS}) target_compile_options(thyaddin PRIVATE -Wall -Wextra -Os) target_link_libraries(thyaddin Gint::Gint) -generate_g3a(TARGET thyaddin OUTPUT "lzy.g3a" - NAME "lzy" ICONS res/icon-uns.png res/icon-sel.png) +generate_g3a(TARGET thyaddin OUTPUT "PCBrawl.g3a" + NAME "" ICONS res/icon-uns.png res/icon-sel.png) diff --git a/Makefile b/Makefile index 66bca25..ad29ded 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ CC ?= gcc CFLAGS = -std=c99 -Wall -Wextra -O3 -I./inc $(shell sdl2-config --cflags) -LDFLAGS = -lSDL2 -lSDL2_image -lSDL2_mixer $(shell sdl2-config --libs) +LDFLAGS = -lSDL2 -lm -lSDL2_image -lSDL2_mixer $(shell sdl2-config --libs) OBJ_NAME = lzy OBJS := $(patsubst %.c,%.o,$(wildcard src/*.c)) @@ -22,8 +22,7 @@ run: $(OBJ_NAME) ./$(OBJ_NAME) format: - @clang-format -style=file -verbose -i src/*.c - @clang-format -style=file -verbose -i inc/*.h + /usr/bin/clang-format -style=file -i src/**.c inc/**.h clean: rm -f $(OBJ_NAME).g3a $(OBJ_NAME) @@ -31,3 +30,4 @@ clean: rm -Rf build-cg .PHONY: cg run run-txt format clean + diff --git a/inc/attack.h b/inc/attack.h new file mode 100644 index 0000000..ef6f81e --- /dev/null +++ b/inc/attack.h @@ -0,0 +1,26 @@ +#pragma once +#include "type.h" + +struct Attack { + struct Vec2 pos; + struct FVec2 dir; + int type; + int active; + int w, h; + int life; + int ice; + int dam; +}; + +struct Attack_table { + int n; + struct Attack *attacks; +}; + +void attack_table_init(void); +void attack_table_update(void); +void attack_table_draw(int timer); +void attack_destroy(struct Attack *attack); +int attack(int x, int y, int dir_x, int dir_y, int type); +int attack_nb(void); +struct Attack * attack_table_collide(int x, int y, int w, int h, int hitbox); diff --git a/inc/bullet.h b/inc/bullet.h new file mode 100644 index 0000000..ced25cc --- /dev/null +++ b/inc/bullet.h @@ -0,0 +1,21 @@ +#pragma once +#include "type.h" + +struct Bullet { + struct Vec2 pos; + struct Vec2 dir; + int v; + int active; +}; + +struct Bullet_table { + int n; + struct Bullet *bullets; +}; + +void bullet_table_init(void); +void bullet_table_update(void); +void bullet_table_draw(int timer); +void bullet_destroy(struct Bullet *bullet); +void bullet_fire(int x, int y, int dir_x, int dir_y, int v); +int bullet_nb(void); diff --git a/inc/conf.h b/inc/conf.h new file mode 100644 index 0000000..7c6278e --- /dev/null +++ b/inc/conf.h @@ -0,0 +1,25 @@ + +#pragma once + +#define PLAYER_S 24 +#define PLAYER_W 24 +#define PLAYER_H 24 +#define PLAYER_ID 2 +#define STAGE_ID 1 + +#define PLAYER_ACC 3 +#define PLAYER_FRIC 0.5 +#define AIR_FRIC 0.2 +#define BASE_COOLDOWN 10 +#define GRAVITY 1 +#define JUMP_H 10 + +#define TILE_S 24 +#define TILESET_W 23 +#define TILESET_H 15 + +#define MAX_BULLETS 20 +#define MAX_ATTACKS 5 +#define MAX_PARTICLES 80 + +#define DRAW_SHIFT 6 diff --git a/inc/level.h b/inc/level.h new file mode 100644 index 0000000..ebb969f --- /dev/null +++ b/inc/level.h @@ -0,0 +1,18 @@ +#pragma once + +#include "type.h" + +struct Level { + int w, h, s; /* width, height, size */ + tile_t *data; +}; + +void level_init(int lvl_id, int chara); +void level_draw(void); +tile_t level_get_px(int x, int y); +tile_t level_get_tile(int x, int y); +int level_count(tile_t tile); +int level_search_i(tile_t tile, int occ); +struct Vec2 level_search_s(tile_t tile, int occ); +struct Vec2 level_get_dim(void); +void level_delete_tile(tile_t tile); diff --git a/inc/lzy.h b/inc/lzy.h index b78ddb1..9e1b7d5 100644 --- a/inc/lzy.h +++ b/inc/lzy.h @@ -93,6 +93,8 @@ int LZY_DrawLine(int x0, int y0, int x1, int y1); int LZY_DrawRect(int x, int y, unsigned int w, unsigned int h); int LZY_DrawFillRect(int x, int y, unsigned int w, unsigned int h); int LZY_DrawTile(unsigned int id, int x, int y); +int LZY_DrawTileEx(unsigned int id, int x, int y, unsigned int w, + unsigned int h); int LZY_DrawChar(unsigned char chr, int x, int y); int LZY_DrawText(const char *text, int x, int y); LZY_Music *LZY_MusicLoad(const char *path); @@ -136,10 +138,10 @@ const char *LZY_GetError(void); #define LZY_TILE_SIZE 16 #endif #ifndef LZY_CHR_WIDTH -#define LZY_CHR_WIDTH LZY_TILE_SIZE +#define LZY_CHR_WIDTH LZY_DISPLAY_WIDTH #endif #ifndef LZY_CHR_HEIGHT -#define LZY_CHR_HEIGHT LZY_TILE_SIZE +#define LZY_CHR_HEIGHT LZY_DISPLAY_HEIGHT #endif #ifndef LZY_FIRST_CHR #define LZY_FIRST_CHR ' ' @@ -180,6 +182,7 @@ int LZY_DrawLine(int x0, int y0, int x1, int y1) { #ifdef FXCG50 #include +#include #include #include #include @@ -311,6 +314,41 @@ int LZY_DrawTile(unsigned int id, int x, int y) { #endif } +int LZY_DrawTileEx(unsigned int id, int x, int y, unsigned int w, + unsigned int h) { +#ifndef LZY_GINT_TILESET + LZY_UNUSED(id); + LZY_UNUSED(x); + LZY_UNUSED(y); + LZY_UNUSED(w); + LZY_UNUSED(h); + return -1; +#else + extern bopti_image_t LZY_GINT_TILESET; + int ix, iy; + + if (w * h == 0) + return -1; + + x += draw_off_x; + y += draw_off_y; + + ix = id % tset_width; + iy = id / tset_width; + + if (ix >= (int)tset_width || ix + w - 1 >= tset_width || + iy >= (int)tset_height || iy + h - 1 >= tset_height) + return -1; + + ix *= LZY_TILE_SIZE; + iy *= LZY_TILE_SIZE; + dsubimage(x, y, &LZY_GINT_TILESET, ix, iy, w * LZY_TILE_SIZE, + h * LZY_TILE_SIZE, DIMAGE_NONE); + + return 0; +#endif +} + int LZY_DrawChar(unsigned char chr, int x, int y) { #ifndef LZY_GINT_FONT LZY_UNUSED(chr); @@ -436,6 +474,10 @@ void LZY_Log(const char *msg) { LZY_UNUSED(msg); } +void LZY_Sleep(int time) { + sleep_ms(time); +} + const char *LZY_GetError(void) { return NULL; } @@ -776,6 +818,48 @@ int LZY_DrawTile(unsigned int id, int x, int y) { return 0; } +int LZY_DrawTileEx(unsigned int id, int x, int y, unsigned int w, + unsigned int h) { + SDL_Rect src, dst; + + if (w * h == 0) { + error = "tile size can't be 0"; + return -1; + } + + if (id >= (unsigned int)(tset_width * tset_height)) { + error = "id exceeds boundaries"; + return -1; + } + + src.x = id % tset_width; + src.y = id / tset_width; + + if (src.x >= tset_width || src.x + w - 1 >= (unsigned int)tset_width || + src.y >= tset_height || + src.y + h - 1 >= (unsigned int)tset_height) { + error = "tile is not in tileset"; + return -1; + } + + src.x *= LZY_TILE_SIZE; + src.y *= LZY_TILE_SIZE; + src.w = w * LZY_TILE_SIZE; + src.h = h * LZY_TILE_SIZE; + + dst.x = x; + dst.y = y; + dst.w = w * LZY_TILE_SIZE; + dst.h = h * LZY_TILE_SIZE; + + if (SDL_RenderCopy(renderer, tset, &src, &dst) < 0) { + error = SDL_GetError(); + return -1; + } + + return 0; +} + int LZY_DrawChar(unsigned char chr, int x, int y) { const unsigned int id = (unsigned int)chr - LZY_FIRST_CHR; SDL_Rect src, dst; @@ -978,5 +1062,10 @@ void LZY_Log(const char *msg) { const char *LZY_GetError(void) { return error; } + +void LZY_Sleep(int time) { + SDL_Delay(time); +} #endif /* SDL2 */ #endif /* LZY_IMPLEMENTATION */ + diff --git a/inc/main.h b/inc/main.h new file mode 100644 index 0000000..64580a6 --- /dev/null +++ b/inc/main.h @@ -0,0 +1,7 @@ +#define LZY_IMPLEMENTATION +#define LZY_GINT_TILESET bimg_tset +#define LZY_GINT_FONT bimg_font +#define LZY_CHR_WIDTH 8 +#define LZY_CHR_HEIGHT 8 +#define LZY_FIRST_CHR ' ' +#define LZY_TILE_SIZE 24 diff --git a/inc/overlay.h b/inc/overlay.h new file mode 100644 index 0000000..652072b --- /dev/null +++ b/inc/overlay.h @@ -0,0 +1,4 @@ +#pragma once + +void overlay_draw(int x, int y, int id, int life); + diff --git a/inc/particle.h b/inc/particle.h new file mode 100644 index 0000000..d160c93 --- /dev/null +++ b/inc/particle.h @@ -0,0 +1,20 @@ +#pragma once +#include "type.h" + +struct Particle { + struct Vec2 pos; + struct Vec2 dir; + int active, id, life; +}; + +struct Particle_table { + int n; + struct Particle *particles; +}; + +void particle_table_init(void); +void particle_table_update(void); +void particle_table_draw(int timer); +void particle_destroy(struct Particle *particle); +void particle_new(int x, int y, int id, int life); +int particle_nb(void); diff --git a/inc/player.h b/inc/player.h new file mode 100644 index 0000000..944dd88 --- /dev/null +++ b/inc/player.h @@ -0,0 +1,22 @@ +#pragma once +#include "type.h" + +struct Cooldown { + int up, down, side, neutral; +}; + +struct Player { + struct Vec2 pos; + struct FVec2 spd; + struct FVec2 rem; + struct Vec2 dir; + struct Cooldown cooldown; + int attack, last_attack, id, active, life, djump; +}; + +void player_init(int chara); +void player_update(void); +void player_draw(int frame); +void player_reset_attack(); +struct Vec2 player_get_pos(void); +int player_get_life(void); diff --git a/inc/sandbag.h b/inc/sandbag.h new file mode 100644 index 0000000..6d37107 --- /dev/null +++ b/inc/sandbag.h @@ -0,0 +1,16 @@ +#pragma once +#include "type.h" + +struct Sandbag { + struct Vec2 pos; + struct FVec2 spd; + struct FVec2 rem; + struct Vec2 dir; + int hitstun, life, iced, active; +}; + +void sandbag_init(void); +void sandbag_update(int frame); +void sandbag_draw(int frame); +struct Vec2 sandbag_get_pos(void); +int sandbag_get_life(void); diff --git a/inc/tools.h b/inc/tools.h new file mode 100644 index 0000000..591c88a --- /dev/null +++ b/inc/tools.h @@ -0,0 +1,6 @@ +#pragma once +#include "type.h" + +void log_int(int x); +int sign(int x); +int length(struct Vec2 *a, struct Vec2 *b); diff --git a/inc/type.h b/inc/type.h new file mode 100644 index 0000000..5731d89 --- /dev/null +++ b/inc/type.h @@ -0,0 +1,12 @@ +#pragma once +#include + +typedef int tile_t; + +struct Vec2 { + int x, y; +}; + +struct FVec2 { + float x, y; +}; diff --git a/res/charas.gif b/res/charas.gif new file mode 100644 index 0000000..aa019aa Binary files /dev/null and b/res/charas.gif differ diff --git a/res/delta.aseprite b/res/delta.aseprite new file mode 100644 index 0000000..e572e05 Binary files /dev/null and b/res/delta.aseprite differ diff --git a/res/duck.aseprite b/res/duck.aseprite new file mode 100644 index 0000000..b8560af Binary files /dev/null and b/res/duck.aseprite differ diff --git a/res/export.gif b/res/export.gif new file mode 100644 index 0000000..47d2305 Binary files /dev/null and b/res/export.gif differ diff --git a/res/export2.gif b/res/export2.gif new file mode 100644 index 0000000..9390105 Binary files /dev/null and b/res/export2.gif differ diff --git a/res/font.png b/res/font.png index 4acde23..3acbb54 100644 Binary files a/res/font.png and b/res/font.png differ diff --git a/res/fxconv-metadata.txt b/res/fxconv-metadata.txt index cbf605c..8f9d068 100644 --- a/res/fxconv-metadata.txt +++ b/res/fxconv-metadata.txt @@ -1,6 +1,8 @@ tset.png: type: bopti-image name: bimg_tset + profile: p8 font.png: type: bopti-image name: bimg_font + profile: p4 diff --git a/res/icon-sel.png b/res/icon-sel.png index 3fefb8a..8c4e605 100644 Binary files a/res/icon-sel.png and b/res/icon-sel.png differ diff --git a/res/icon-uns.png b/res/icon-uns.png index 6381b23..0e86909 100644 Binary files a/res/icon-uns.png and b/res/icon-uns.png differ diff --git a/res/level.lua b/res/level.lua new file mode 100644 index 0000000..7e50c7b --- /dev/null +++ b/res/level.lua @@ -0,0 +1,73 @@ +return { + version = "1.5", + luaversion = "5.1", + tiledversion = "1.8.2", + orientation = "orthogonal", + renderorder = "right-down", + width = 17, + height = 10, + tilewidth = 24, + tileheight = 24, + nextlayerid = 2, + nextobjectid = 1, + properties = {}, + tilesets = { + { + name = "tset", + firstgid = 1, + tilewidth = 24, + tileheight = 24, + spacing = 0, + margin = 0, + columns = 23, + image = "tset.png", + imagewidth = 552, + imageheight = 360, + objectalignment = "unspecified", + tileoffset = { + x = 0, + y = 0 + }, + grid = { + orientation = "orthogonal", + width = 24, + height = 24 + }, + properties = {}, + wangsets = {}, + tilecount = 345, + tiles = {} + } + }, + layers = { + { + type = "tilelayer", + x = 0, + y = 0, + width = 17, + height = 10, + id = 1, + name = "Tile Layer 1", + visible = true, + opacity = 1, + offsetx = 0, + offsety = 0, + parallaxx = 1, + parallaxy = 1, + properties = {}, + encoding = "lua", + data = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 18, 20, 0, 0, 0, 0, 0, 0, 0, 18, 20, 0, 0, 0, + 0, 0, 0, 41, 67, 19, 19, 19, 19, 19, 19, 19, 69, 43, 0, 0, 0, + 0, 0, 0, 64, 46, 44, 65, 65, 65, 65, 65, 46, 44, 66, 0, 0, 0, + 0, 0, 0, 0, 41, 43, 0, 0, 0, 0, 0, 41, 43, 0, 0, 0, 0 + } + } + } +} diff --git a/res/level.tmx b/res/level.tmx new file mode 100644 index 0000000..9b49414 --- /dev/null +++ b/res/level.tmx @@ -0,0 +1,20 @@ + + + + + + + +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,45,45,0,0,0,0,0,0,0,45,45,0,0,0, +0,0,0,18,20,0,0,0,0,0,0,0,18,20,0,0,0, +0,0,0,41,67,19,19,19,19,19,19,19,69,43,0,0,0, +0,0,0,64,42,42,65,65,65,65,65,42,42,66,0,0,0, +0,0,0,0,41,43,0,0,0,0,0,41,43,0,0,0,0 + + + diff --git a/res/level2.lua b/res/level2.lua new file mode 100644 index 0000000..af1cef0 --- /dev/null +++ b/res/level2.lua @@ -0,0 +1,73 @@ +return { + version = "1.5", + luaversion = "5.1", + tiledversion = "1.8.2", + orientation = "orthogonal", + renderorder = "right-down", + width = 17, + height = 10, + tilewidth = 24, + tileheight = 24, + nextlayerid = 2, + nextobjectid = 1, + properties = {}, + tilesets = { + { + name = "tset", + firstgid = 1, + tilewidth = 24, + tileheight = 24, + spacing = 0, + margin = 0, + columns = 23, + image = "tset.png", + imagewidth = 552, + imageheight = 360, + objectalignment = "unspecified", + tileoffset = { + x = 0, + y = 0 + }, + grid = { + orientation = "orthogonal", + width = 24, + height = 24 + }, + properties = {}, + wangsets = {}, + tilecount = 345, + tiles = {} + } + }, + layers = { + { + type = "tilelayer", + x = 0, + y = 0, + width = 17, + height = 10, + id = 1, + name = "Tile Layer 1", + visible = true, + opacity = 1, + offsetx = 0, + offsety = 0, + parallaxx = 1, + parallaxy = 1, + properties = {}, + encoding = "lua", + data = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 84, 85, 86, 87, 88, 89, 90, 91, 92, 84, 85, 0, 0, 0, + 0, 0, 0, 107, 108, 109, 110, 111, 112, 113, 114, 115, 107, 108, 0, 0, 0, + 0, 0, 0, 130, 131, 132, 133, 134, 135, 136, 137, 138, 130, 131, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + } + } + } +} diff --git a/res/level3.lua b/res/level3.lua new file mode 100644 index 0000000..d40e56c --- /dev/null +++ b/res/level3.lua @@ -0,0 +1,103 @@ +return { + version = "1.5", + luaversion = "5.1", + tiledversion = "1.8.4", + orientation = "orthogonal", + renderorder = "right-down", + width = 17, + height = 10, + tilewidth = 24, + tileheight = 24, + nextlayerid = 4, + nextobjectid = 1, + backgroundcolor = { 255, 255, 255 }, + properties = {}, + tilesets = { + { + name = "tset", + firstgid = 1, + tilewidth = 24, + tileheight = 24, + spacing = 0, + margin = 0, + columns = 23, + image = "tset.png", + imagewidth = 552, + imageheight = 360, + objectalignment = "unspecified", + tileoffset = { + x = 0, + y = 0 + }, + grid = { + orientation = "orthogonal", + width = 24, + height = 24 + }, + properties = {}, + wangsets = {}, + tilecount = 345, + tiles = {} + } + }, + layers = { + { + type = "tilelayer", + x = 0, + y = 0, + width = 17, + height = 10, + id = 3, + name = "Tile Layer 2", + visible = true, + opacity = 1, + offsetx = 0, + offsety = 0, + parallaxx = 1, + parallaxy = 1, + properties = {}, + encoding = "lua", + data = { + 240, 262, 262, 0, 288, 242, 241, 242, 242, 242, 240, 242, 288, 0, 262, 262, 241, + 0, 242, 242, 0, 288, 242, 242, 242, 242, 242, 242, 242, 288, 0, 242, 242, 0, + 0, 262, 262, 0, 0, 241, 263, 0, 0, 0, 264, 240, 0, 0, 262, 262, 0, + 0, 0, 0, 0, 263, 0, 242, 242, 242, 242, 242, 0, 264, 0, 0, 0, 0, + 286, 287, 0, 0, 240, 0, 241, 242, 242, 242, 240, 0, 242, 0, 0, 286, 287, + 0, 0, 0, 0, 0, 0, 0, 262, 262, 262, 0, 0, 240, 0, 288, 0, 0, + 263, 0, 242, 0, 239, 239, 285, 262, 262, 262, 285, 239, 239, 0, 241, 0, 264, + 242, 0, 0, 264, 0, 0, 0, 0, 0, 0, 0, 0, 0, 263, 0, 0, 242, + 242, 286, 287, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242, 286, 287, 242, + 242, 263, 264, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242, 242, 263, 242 + } + }, + { + type = "tilelayer", + x = 0, + y = 0, + width = 17, + height = 10, + id = 1, + name = "Tile Layer 1", + visible = true, + opacity = 1, + offsetx = 0, + offsety = 0, + parallaxx = 1, + parallaxy = 1, + properties = {}, + encoding = "lua", + data = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 183, 182, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183, 182, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 177, 156, 157, 159, 155, 155, 155, 159, 156, 157, 177, 0, 0, 0, + 0, 0, 0, 161, 179, 180, 161, 160, 160, 160, 161, 179, 180, 161, 0, 0, 0, + 0, 0, 0, 161, 161, 161, 161, 160, 160, 160, 161, 161, 161, 161, 0, 0, 0 + } + } + } +} diff --git a/res/poudingue.aseprite b/res/poudingue.aseprite new file mode 100644 index 0000000..c8a7215 Binary files /dev/null and b/res/poudingue.aseprite differ diff --git a/res/rdp.png b/res/rdp.png new file mode 100644 index 0000000..8880cb4 Binary files /dev/null and b/res/rdp.png differ diff --git a/res/reveal.aseprite b/res/reveal.aseprite new file mode 100644 index 0000000..bde00a9 Binary files /dev/null and b/res/reveal.aseprite differ diff --git a/res/reveal2.aseprite b/res/reveal2.aseprite new file mode 100644 index 0000000..c1456fa Binary files /dev/null and b/res/reveal2.aseprite differ diff --git a/res/reveal2.png b/res/reveal2.png new file mode 100644 index 0000000..57fc9b3 Binary files /dev/null and b/res/reveal2.png differ diff --git a/res/reveal3.aseprite b/res/reveal3.aseprite new file mode 100644 index 0000000..ab621c8 Binary files /dev/null and b/res/reveal3.aseprite differ diff --git a/res/sakimi.aseprite b/res/sakimi.aseprite new file mode 100644 index 0000000..6f46bbb Binary files /dev/null and b/res/sakimi.aseprite differ diff --git a/res/tset.png b/res/tset.png index ea428d6..6818cce 100644 Binary files a/res/tset.png and b/res/tset.png differ diff --git a/src/attack.c b/src/attack.c new file mode 100644 index 0000000..ca4caff --- /dev/null +++ b/src/attack.c @@ -0,0 +1,300 @@ +#include "attack.h" +#include "bullet.h" +#include "player.h" +#include "conf.h" +#include "tools.h" +#include "level.h" +#include "particle.h" +#include "lzy.h" + +#include +#include + +static struct Attack_table attack_table; + +static void attack_table_free(void); +static void attack_update(struct Attack *attack); +static void attack_draw(struct Attack *attack, int timer); +static int attack_collide(struct Attack *attack, int x, int y, int w, int h, int hitbox); + +void +attack_table_init(void) +{ + attack_table_free(); + attack_table.attacks = malloc(MAX_ATTACKS * sizeof(struct Attack)); + attack_table.n = 0; + + for (int i = 0; i < MAX_ATTACKS; ++i) { + attack_table.attacks[i].active = 0; + } +} + +void +attack_table_free(void) +{ + if (attack_table.attacks != NULL) { + attack_table.attacks = NULL; + } +}; + +int attack(int x, int y, int dir_x, int dir_y, int type) { + int cooldown = 5; + for (int i = 0; i < MAX_ATTACKS; ++i) { + if (!attack_table.attacks[i].active) { + struct Attack * att = &attack_table.attacks[i]; + *att = (struct Attack){ + .pos = (struct Vec2){.x = x, .y = y}, + .type = type, + .active = 1, + .ice = 0, + .dam = 0, + }; + switch(type){ + case 1: + att->w = 5; + att->h = 5; + att->life = 2; + att->dir = (struct FVec2){.x = dir_x * 2, .y = dir_y * 0.5}; + att->dam = 2; + cooldown = 10; + particle_new(att->pos.x, att->pos.y, dir_x > 0 ? 7 : 8, att->life); + break; + case 2: + att->w = 10; + att->h = 10; + att->life = 2; + att->dam = 4; + att->dir = (struct FVec2){.x = 0, .y = -2}; + cooldown = 15; + particle_new(att->pos.x, att->pos.y, 9, att->life); + break; + case 3: + att->w = 10; + att->h = 5; + att->life = 2; + att->dam = 3; + att->dir = (struct FVec2){.x = 0, .y = 1.5}; + cooldown = 10; + particle_new(att->pos.x, att->pos.y, 4, att->life); + break; + case 4: + att->w = 16; + att->h = 16; + att->life = 3; + att->dam = 1; + att->dir = (struct FVec2){.x = dir_x * 0.5, .y = 0.5}; + cooldown = 60; + att->ice = 1; + break; + case 5: + att->pos.x -= dir_x * 2; + att->pos.y += 3; + att->w = 5; + att->h = 8; + att->life = 2; + att->dam = 2; + att->dir = (struct FVec2){.x = dir_x * 1.5, .y = dir_y * 0.5}; + cooldown = 10; + particle_new(att->pos.x, att->pos.y + 4, dir_x > 0 ? 7 : 8, att->life); + break; + case 6: + att->w = 6; + att->pos.x -= att->w / 2; + att->h = 2; + att->life = 80; + att->dam = 5; + att->dir = (struct FVec2){.x = 0, .y = -0.5}; + cooldown = 20; + bullet_fire(att->pos.x, att->pos.y, 0, 1, 8); + particle_new(att->pos.x, att->pos.y, 9, 2); + break; + case 7: + att->w = 13; + att->h = 4; + att->life = 2; + att->dam = 4; + att->dir = (struct FVec2){.x = 0, .y = 1.5}; + cooldown = 10; + particle_new(att->pos.x, att->pos.y, 3, att->life); + break; + case 8: + att->w = 8; + att->h = 8; + att->life = 2; + att->dam = 2; + att->dir = (struct FVec2){.x = dir_x * 0.25, .y = 1}; + cooldown = 10; + break; + case 9: + att->pos.x += dir_x * 4; + att->w = 8; + att->h = 12; + att->life = 2; + att->dam = 3; + att->dir = (struct FVec2){.x = dir_x * 2.5, .y = dir_y * 1}; + cooldown = 10; + particle_new(att->pos.x - dir_x * 4, att->pos.y, dir_x > 0 ? 7 : 8, att->life); + break; + case 10: + att->pos.y += 2; + att->w = 12; + att->h = 6; + att->life = 2; + att->dam = 5; + att->dir = (struct FVec2){.x = 0, .y = -4}; + cooldown = 15; + particle_new(att->pos.x, att->pos.y, 9, att->life); + break; + case 11: + att->w = 10; + att->h = 5; + att->life = 2; + att->dam = 5; + att->dir = (struct FVec2){.x = 0, .y = 1.5}; + cooldown = 10; + particle_new(att->pos.x, att->pos.y, 4, att->life); + break; + case 12: + att->w = 18; + att->h = 18; + att->life = 1; + att->dam = 6; + att->dir = (struct FVec2){.x = dir_x * 2, .y = 1.5}; + particle_new(att->pos.x, att->pos.y, 0, 2); + particle_new(att->pos.x + dir_x * 8, att->pos.y - 8, 0, 4); + particle_new(att->pos.x + dir_x * 16, att->pos.y - 16, 0, 8); + cooldown = 30; + break; + case 13: + att->w = 5; + att->h = 5; + att->life = 2; + att->dam = 2; + att->dir = (struct FVec2){.x = dir_x * 2, .y = dir_y * 0.5}; + cooldown = 10; + particle_new(att->pos.x, att->pos.y, dir_x > 0 ? 7 : 8, att->life); + break; + case 14: + att->w = 10; + att->h = 10; + att->life = 2; + att->dir = (struct FVec2){.x = 0, .y = -2}; + cooldown = 15; + att->dam = 3; + particle_new(att->pos.x, att->pos.y, 9, att->life); + break; + case 15: + att->w = 10; + att->h = 5; + att->life = 2; + att->dir = (struct FVec2){.x = 0, .y = 1.5}; + cooldown = 10; + att->dam = 3; + particle_new(att->pos.x, att->pos.y, 4, att->life); + break; + case 16: + att->w = 16; + att->h = 16; + att->life = 60; + att->dir = (struct FVec2){.x = 0, .y = 0}; + cooldown = 120; + att->dam = 1; + particle_new(att->pos.x, att->pos.y, 6, att->life); + break; + default: + att->w = 0; + att->h = 0; + att->life = 0 ; + att->dir = (struct FVec2){.x = dir_x, .y = 0}; + cooldown = 0; + break; + } + attack_table.attacks[i].pos.x -= attack_table.attacks[i].w / 2; + attack_table.attacks[i].pos.y -= attack_table.attacks[i].h / 2; + break; + } + } + ++attack_table.n; + return cooldown; +} + +void +attack_table_update(void) +{ + for (int i = 0; i < MAX_ATTACKS; ++i) { + if (attack_table.attacks[i].active) { + attack_update(&attack_table.attacks[i]); + } + } +} + +void +attack_update(struct Attack *attack) +{ + if (attack->type == 6) { + attack->pos.y += 8; + } + + --attack->life; + if (attack->life < 0) { + player_reset_attack(); + attack_destroy(attack); + } +} + +void +attack_table_draw(int timer) +{ + for (int i = 0; i < MAX_ATTACKS; ++i) { + if (attack_table.attacks[i].active) { + attack_draw(&attack_table.attacks[i], timer); + } + } +} + +void +attack_draw(struct Attack *attack, int timer) +{ +} + +void +attack_destroy(struct Attack *attack) +{ + attack->active = 0; + --attack_table.n; +} + +int +attack_nb(void) +{ + return attack_table.n; +} + +struct Attack * +attack_table_collide(int x, int y, int w, int h, int hitbox) +{ + for (int i = 0; i < MAX_ATTACKS; ++i) { + if (attack_table.attacks[i].active) { + if(attack_collide(&attack_table.attacks[i], x, y, w, h, hitbox)) { + return &attack_table.attacks[i]; + } + } + } + return NULL; +} + +int +attack_collide(struct Attack *attack, int x, int y, int w, int h, int hitbox) +{ + if ((attack->pos.x + hitbox < x + w && + attack->pos.x + attack->w - hitbox > x && + attack->pos.y + hitbox < y + h && + attack->pos.y + attack->h - hitbox > y) || + (attack->pos.x + hitbox > x && + attack->pos.x + attack->w - hitbox < x + w && + attack->pos.y + hitbox > y && + attack->pos.y + attack->h - hitbox < y + h)) { + return 1; + } + return 0; +} diff --git a/src/bullet.c b/src/bullet.c new file mode 100644 index 0000000..edd408a --- /dev/null +++ b/src/bullet.c @@ -0,0 +1,101 @@ +#include "bullet.h" +#include "conf.h" +#include "tools.h" +#include "level.h" +#include "lzy.h" + +#include +#include + +static struct Bullet_table bullet_table; + +static void bullet_table_free(void); +static void bullet_update(struct Bullet *bullet); +static void bullet_draw(struct Bullet *bullet, int timer); + +void +bullet_table_init(void) +{ + bullet_table_free(); + bullet_table.bullets = malloc(MAX_BULLETS * sizeof(struct Bullet)); + bullet_table.n = 0; + + for (int i = 0; i < MAX_BULLETS; ++i) { + bullet_table.bullets[i].active = 0; + } +} + +void +bullet_table_free(void) +{ + if (bullet_table.bullets != NULL) { + bullet_table.bullets = NULL; + } +}; + +void bullet_fire(int x, int y, int dir_x, int dir_y, int v) { + for (int i = 0; i < MAX_BULLETS; ++i) { + if (!bullet_table.bullets[i].active) { + bullet_table.bullets[i] = (struct Bullet){ + .pos = (struct Vec2){.x = x - 8, .y = y - 8}, + .dir = (struct Vec2){.x = dir_x, .y = dir_y}, + .v = v, + .active = 1}; + break; + } + } + ++bullet_table.n; +} + +void +bullet_table_update(void) +{ + for (int i = 0; i < MAX_BULLETS; ++i) { + if (bullet_table.bullets[i].active) { + bullet_update(&bullet_table.bullets[i]); + } + } +} + +void +bullet_update(struct Bullet *bullet) +{ + bullet->pos.x += bullet->dir.x * bullet->v; + bullet->pos.y += bullet->dir.y * bullet->v; + + /* boom */ + const struct Vec2 level_dim = level_get_dim(); + if (bullet->pos.x < -72 || bullet->pos.x > level_dim.x * TILE_S + 48 || + bullet->pos.y < -96 || bullet->pos.y > level_dim.y * TILE_S + 48) { + bullet_destroy(bullet); + } +} + +void +bullet_table_draw(int timer) +{ + for (int i = 0; i < MAX_BULLETS; ++i) { + if (bullet_table.bullets[i].active) { + bullet_draw(&bullet_table.bullets[i], timer); + } + } +} + +void +bullet_draw(struct Bullet *bullet, int timer) +{ + LZY_DrawTile(15, bullet->pos.x, bullet->pos.y); +} + +void +bullet_destroy(struct Bullet *bullet) +{ + bullet->active = 0; + --bullet_table.n; +} + +int +bullet_nb(void) +{ + return bullet_table.n; +} diff --git a/src/level.c b/src/level.c new file mode 100644 index 0000000..498dfa5 --- /dev/null +++ b/src/level.c @@ -0,0 +1,235 @@ +/* Ne pas lire ce code svp merci */ + +#include "level.h" +#include "conf.h" +#include "player.h" +#include "sandbag.h" +#include "bullet.h" +#include "attack.h" +#include "particle.h" +#include "lzy.h" + +#include +#include + +static int id; +static struct Level level; +static struct Level bg; +static void level_free(void); +static void level_load(void); +static void level_draw_bg(void); + +void +level_init(int lvl_id, int chara) +{ + level = (struct Level){ + .w = 17, + .h = 10, + }; + level.s = level.w * level.h; + id = lvl_id; + level_free(); + level_load(); + + player_init(chara); + sandbag_init(); + bullet_table_init(); + attack_table_init(); + particle_table_init(); +} + +void +level_draw(void) +{ + level_draw_bg(); + for (int m = 0; m < level.h; ++m) { + for (int n = 0; n < level.w; ++n) { + tile_t tile = level_get_tile(n, m); + + LZY_DrawTile(tile, n * TILE_S - DRAW_SHIFT, m * TILE_S); + } + } +} + +tile_t +level_get_px(int x, int y) +{ + x += DRAW_SHIFT; + const int pos = x / TILE_S + y / TILE_S * level.w; + if (pos > level.s || pos < 0 || x < 0 || x > TILE_S * level.w) return 0; + const int tile = level.data[pos]; + return tile - (tile != 0); +} + +tile_t +level_get_tile(int x, int y) +{ + if (x + y * level.w > level.s || x + y * level.w < 0) return 0; + const int tile = level.data[x + y * level.w]; + return tile - (tile != 0); +} + +int +level_count(tile_t tile) +{ + int i = 0; + for (int t = 0; t < level.h * level.w - 1; ++t) { + if (level.data[t] == tile) { + ++i; + } + } + return i; +} + +int +level_search_i(tile_t tile, int occ) +{ + for (int t = 0; t < level.h * level.w - 1; ++t) { + if (level.data[t] == tile) { + if (!(occ - 1)) { + return t; + } else { + --occ; + } + } + } + return 0; +} + +struct Vec2 +level_search_s(tile_t tile, int occ) +{ + for (int m = 0; m < level.h; ++m) { + for (int n = 0; n < level.w; ++n) { + if (level.data[n + m * level.w] == tile) { + if (!(occ - 1)) { + return (struct Vec2){n, m}; + } else { + --occ; + } + } + } + } + return (struct Vec2){0, 0}; +} + +struct Vec2 +level_get_dim(void) +{ + return (struct Vec2){level.w, level.h}; +} + +static void +level_free(void) +{ + level.data = (tile_t *)malloc(170 * sizeof(tile_t)); +} + +static void +level_load(void) +{ + /* TODO : LEVEL LOADING */ + tile_t data[3][170] = {{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 18, 20, 0, 0, 0, 0, 0, 0, 0, 18, 20, 0, 0, 0, + 0, 0, 0, 41, 67, 19, 19, 19, 19, 19, 19, 19, 69, 43, 0, 0, 0, + 0, 0, 0, 64, 46, 44, 65, 65, 65, 65, 65, 46, 44, 66, 0, 0, 0, + 0, 0, 0, 0, 41, 43, 0, 0, 0, 0, 0, 41, 43, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 84, 85, 86, 87, 88, 89, 90, 91, 92, 84, 85, 0, 0, 0, + 0, 0, 0, 107, 108, 109, 110, 111, 112, 113, 114, 115, 107, 108, 0, 0, 0, + 0, 0, 0, 130, 131, 132, 133, 134, 135, 136, 137, 138, 130, 131, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 183, 182, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183, 182, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 177, 156, 157, 159, 155, 155, 155, 159, 156, 157, 177, 0, 0, 0, + 0, 0, 0, 161, 179, 180, 161, 160, 160, 160, 161, 179, 180, 161, 0, 0, 0, + 0, 0, 0, 161, 161, 161, 161, 160, 160, 160, 161, 161, 161, 161, 0, 0, 0}}; + + memcpy(level.data, data[id], sizeof(data[0])); + + if(id==2) { + bg.data = (tile_t *)malloc(170 * sizeof(tile_t)); + + tile_t owo[170] = {240, 262, 262, 0, 288, 242, 241, 242, 242, 242, 240, 242, 288, 0, 262, 262, 241, + 0, 242, 242, 0, 288, 242, 242, 242, 242, 242, 242, 242, 288, 0, 242, 242, 0, + 0, 262, 262, 0, 0, 241, 263, 0, 0, 0, 264, 240, 0, 0, 262, 262, 0, + 0, 0, 0, 0, 263, 0, 242, 242, 242, 242, 242, 0, 264, 0, 0, 0, 0, + 286, 287, 0, 0, 240, 0, 241, 242, 242, 242, 240, 0, 242, 0, 0, 286, 287, + 0, 0, 0, 0, 0, 0, 0, 262, 262, 262, 0, 0, 240, 0, 288, 0, 0, + 263, 0, 242, 0, 239, 239, 285, 262, 262, 262, 285, 239, 239, 0, 241, 0, 264, + 242, 0, 0, 264, 0, 0, 0, 0, 0, 0, 0, 0, 0, 263, 0, 0, 242, + 242, 286, 287, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242, 286, 287, 242, + 242, 263, 264, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242, 242, 263, 242}; + memcpy(bg.data, owo, sizeof(owo)); + } +} + +static void +level_draw_bg(void) { + switch(id){ + case 0: + default: + for (int i = 0; i < 3; ++i) { + LZY_DrawTileEx(115, i * TILE_S * 6, 0, 6, 10); + } + break; + + case 1: + LZY_DrawSetColor(3, 2, 30); + LZY_DrawFillRect(0, 112, 396, 112); + for (int i = 0; i < level.w; ++i) { + LZY_DrawTileEx(121, i * TILE_S, 0, 1, 5); + } + LZY_DrawTileEx(122, 162, 94, 3, 2); + LZY_DrawTileEx(168, 66, 216, 2, 1); + LZY_DrawTileEx(168, 282, 216, 2, 1); + LZY_DrawTileEx(170, 66, 120, 2, 1); + LZY_DrawTileEx(170, 282, 120, 2, 1); + + LZY_DrawTile(283, -6, 144); + LZY_DrawTile(283, 42, 216); + LZY_DrawTile(283, 42, 120); + LZY_DrawTile(283, 378, 120); + LZY_DrawTileEx(282, 330, 144, 1, 3); + LZY_DrawTileEx(236, 18, 168, 1, 2); + LZY_DrawTileEx(236, 354, 144, 1, 2); + LZY_DrawTileEx(306, 378, 192, 1, 2); + LZY_DrawTileEx(237, -6, 192, 1, 2); + break; + + case 2: + LZY_DrawSetColor(255, 255, 255); + for (int m = 0; m < level.h; ++m) { + for (int n = 0; n < level.w; ++n) { + int tile = bg.data[n + m * level.w]; + tile = tile - (tile != 0); + if (tile) LZY_DrawTile(tile, n * TILE_S - 6, m * TILE_S); + else LZY_DrawFillRect(n * TILE_S - 6, m * TILE_S, 24, 24); + } + } + } +} + +void level_delete_tile(tile_t tile) { + for (int m = 0; m < level.h; ++m) { + for (int n = 0; n < level.w; ++n) { + if (level_get_tile(n, m) == tile) level.data[m + n * level.w] = 0; + } + } +} diff --git a/src/main.c b/src/main.c index 8286b7f..2663de2 100644 --- a/src/main.c +++ b/src/main.c @@ -1,54 +1,86 @@ -#define LZY_IMPLEMENTATION -#define LZY_GINT_TILESET bimg_tset -#define LZY_GINT_FONT bimg_font -#define LZY_CHR_WIDTH 16 -#define LZY_CHR_HEIGHT 16 -#define LZY_FIRST_CHR ' ' +#include "main.h" #include "lzy.h" +#include "player.h" +#include "bullet.h" +#include "attack.h" +#include "level.h" +#include "sandbag.h" +#include "overlay.h" +#include "particle.h" -static const int speed = 4; +#include +#include -int main(int argc, const char **argv) { - int x = 0; - int y = 0; +static int frame, chara, level; +static int log_init(int x); +static int init(int argc, const char **argv); +static void update(void); +static void draw(int frame); +static int menu(void); +static void draw_bg(int frame); +/* debug */ + +int +init(int argc, const char **argv) +{ + srand(69); if (LZY_Init(argc, argv, "lzy example", 30, "res/tset.png", "res/font.png")) { LZY_Log(LZY_GetError()); LZY_Quit(); return 1; } - LZY_Log("initialisation was a success!"); + + menu(); + + level_init(level, chara); + frame = 0; + return 0; +} + +void +update(void) +{ + LZY_CycleEvents(); + player_update(); + sandbag_update(frame); + bullet_table_update(); + attack_table_update(); + particle_table_update(); +} + +void +draw(int frame) +{ + /* draw */ + LZY_DrawBegin(); + { + level_draw(); + player_draw(frame); + sandbag_draw(frame); + bullet_table_draw(frame); + attack_table_draw(frame); + particle_table_draw(frame); + + overlay_draw(114, 176, chara, player_get_life()); + overlay_draw(210, 176, -1, sandbag_get_life()); + } + LZY_DrawEnd(); +} + +int +main(int argc, const char **argv) +{ + if (init(argc, argv)) { + return 1; + } /* error */ while (!LZY_ShouldQuit()) { - /* update */ - LZY_CycleEvents(); + update(); + draw(frame); - /* move player */ - if (LZY_KeyDown(LZYK_LEFT)) - x -= speed; - if (LZY_KeyDown(LZYK_RIGHT)) - x += speed; - if (LZY_KeyDown(LZYK_UP)) - y -= speed; - if (LZY_KeyDown(LZYK_DOWN)) - y += speed; - - /* draw */ - LZY_DrawBegin(); - { - /* clear screen */ - LZY_DrawSetColor(0, 0, 0); - LZY_DrawClear(); - - /* draw yellow line between player and topleft corner */ - LZY_DrawSetColor(255, 255, 0); - LZY_DrawLine(x, y, 0, 0); - - /* draw player */ - LZY_DrawTile(1, x, y); - } - LZY_DrawEnd(); + frame += 1; } LZY_Log("cya"); @@ -56,3 +88,152 @@ int main(int argc, const char **argv) { return 0; } + +int menu(void) { + /* main loop of the menu */ + int running = 1; + int frame = 0; + while(running) { + LZY_CycleEvents(); + + LZY_DrawBegin(); + { + draw_bg(frame); + LZY_DrawTileEx(247, LZY_DISPLAY_WIDTH / 2 - 72, 30, 6, 5); + if (frame % 16 < 8) { + LZY_DrawText("- PRESS SHIFT -", 134, 181); + LZY_DrawText("- PRESS SHIFT -", 134, 180); + } + } + LZY_DrawEnd(); + running = !LZY_KeyDown(LZYK_O); + frame += 1; + } + + while(LZY_KeyDown(LZYK_O)) {LZY_CycleEvents();} + running = 1; + int selec = 1; + int wait = 0; + + while(running) { + LZY_CycleEvents(); + + LZY_DrawBegin(); + { + draw_bg(frame); + LZY_DrawTile(61, 186 + (selec - 2.5) * 48, 64.0f + sin((float)frame / 5) * 5.0f); + for (int i=1; i<5; ++i) { + LZY_DrawTile(i * 23, 186 + (i - 2.5) * 48, 100); + } + + switch (selec) { + case 1: + LZY_DrawText("DELTA", 178, 151); + LZY_DrawText("DELTA", 178, 150); + LZY_DrawText("PAR MASSENA", 16, 200); + LZY_DrawText("DANS FROZEN FRENZY", 16, 208); + break; + case 2: + LZY_DrawText("GRAVITY DUCK", 150, 151); + LZY_DrawText("GRAVITY DUCK", 150, 150); + LZY_DrawText("PAR PIEROTLL", 16, 200); + LZY_DrawText("DANS GRAVITY DUCK", 16, 208); + break; + case 3: + LZY_DrawText("AVENTURIER POUDINGUE", 118, 151); + LZY_DrawText("AVENTURIER POUDINGUE", 118, 150); + LZY_DrawText("PAR DRAK", 16, 200); + LZY_DrawText("DANS AVENTURA, LE ROYAUME POUDINGUE", 16, 208); + break; + case 4: + LZY_DrawText("SAKIMI HAKYU", 150, 151); + LZY_DrawText("SAKIMI HAKYU", 150, 150); + LZY_DrawText("PAR REDEYES", 16, 200); + LZY_DrawText("DANS SWORD BURST ZERO", 16, 208); + break; + } + } + LZY_DrawEnd(); + running = !LZY_KeyDown(LZYK_O); + if(LZY_KeyDown(LZYK_LEFT) && selec > 1 && !wait) { + selec -= 1; + wait = 5; + }; + if(LZY_KeyDown(LZYK_RIGHT) && selec < 4 && !wait) { + selec += 1; + wait = 5; + }; + frame += 1; + if (wait > 0) --wait; + } + + while(LZY_KeyDown(LZYK_O)) {LZY_CycleEvents();} + running = 1; + int selec_level = 1; + wait = 0; + + while(running) { + LZY_CycleEvents(); + + LZY_DrawBegin(); + { + draw_bg(frame); + LZY_DrawTile(61, 90 + (selec_level - 1) * 96, 40.0f + sin((float)frame / 5) * 5.0f); + for (int i=1; i<4; ++i) { + LZY_DrawTileEx(307 + (i - 1) * 3, 66 + (i - 1) * 96, 76, 3, 2); + } + + switch (selec_level) { + case 1: + LZY_DrawText("GRAVITY FOREST DX", 130, 151); + LZY_DrawText("GRAVITY FOREST DX", 130, 150); + break; + case 2: + LZY_DrawText("SANCTUAIRE DE RECUPERATION", 90, 151); + LZY_DrawText("SANCTUAIRE DE RECUPERATION", 90, 150); + break; + case 3: + LZY_DrawText("PLANETE PLATFORMER", 126, 151); + LZY_DrawText("PLANETE PLATFORMER", 126, 150); + break; + } + } + LZY_DrawEnd(); + running = !LZY_KeyDown(LZYK_O); + if(LZY_KeyDown(LZYK_LEFT) && selec_level > 1 && !wait) { + selec_level -= 1; + wait = 5; + }; + if(LZY_KeyDown(LZYK_RIGHT) && selec_level < 3 && !wait) { + selec_level += 1; + wait = 5; + }; + frame += 1; + if (wait > 0) --wait; + } + + chara = selec - 1; + level = selec_level - 1; + return 1; +} + +void draw_bg(int frame) { + LZY_DrawSetColor(240, 181, 65); + LZY_DrawClear(); + LZY_DrawSetColor(255, 137, 51); + + for (int x = frame%32-32; x < LZY_DISPLAY_WIDTH+32 ; x += 32){ + for (int y = frame%32-32; y < LZY_DISPLAY_HEIGHT+32 ; y += 32){ + LZY_DrawRect(x-1, y-1, 32, 32); + LZY_DrawRect(x, y, 32, 32); + LZY_DrawRect(x+1, y+1, 32, 32); + } + } + + LZY_DrawSetColor(207, 117, 43); + for (int x = (frame*2)%32-32; x < LZY_DISPLAY_WIDTH+32 ; x += 32){ + for (int y = (frame*2)%32-32; y < LZY_DISPLAY_HEIGHT+32 ; y += 32){ + LZY_DrawRect(x, y, 32, 32); + } + } +} diff --git a/src/overlay.c b/src/overlay.c new file mode 100644 index 0000000..63f49cc --- /dev/null +++ b/src/overlay.c @@ -0,0 +1,14 @@ +#include "conf.h" +#include "lzy.h" + +static void draw_num(int i, int x, int y) { + LZY_DrawTile(35 + i % 2 + (i / 2) * TILESET_W, x, y); +} + +void overlay_draw(int x, int y, int id, int life) { + LZY_DrawTileEx(id == -1 ? 243 : 191 + id * 4, x, y, 4, 2); + if (life > 100) draw_num(life / 100 , x + 12, y + 12); + if (life > 10) draw_num((life % 100 / 10), x + 30, y + 12); + draw_num(life % 10, x + 48, y + 12); + LZY_DrawTile(60, x + 62 , y + 12); +} diff --git a/src/particle.c b/src/particle.c new file mode 100644 index 0000000..4e7c47b --- /dev/null +++ b/src/particle.c @@ -0,0 +1,98 @@ +#include "particle.h" +#include "conf.h" +#include "tools.h" +#include "level.h" +#include "lzy.h" + +#include +#include + +static struct Particle_table particle_table; + +static void particle_table_free(void); +static void particle_update(struct Particle *particle); +static void particle_draw(struct Particle *particle, int timer); + +void +particle_table_init(void) +{ + particle_table_free(); + particle_table.particles = malloc(MAX_PARTICLES * sizeof(struct Particle)); + particle_table.n = 0; + + for (int i = 0; i < MAX_PARTICLES; ++i) { + particle_table.particles[i].active = 0; + } +} + +void +particle_table_free(void) +{ + if (particle_table.particles != NULL) { + particle_table.particles = NULL; + } +}; + +void particle_new(int x, int y, int id, int life) { + for (int i = 0; i < MAX_PARTICLES; ++i) { + if (!particle_table.particles[i].active) { + particle_table.particles[i] = (struct Particle){ + .pos = (struct Vec2){.x = x - TILE_S / 2, .y = y - TILE_S / 2}, + .id = id, + .life = life, + .active = 1}; + break; + } + } + ++particle_table.n; +} + +void +particle_table_update(void) +{ + for (int i = 0; i < MAX_PARTICLES; ++i) { + if (particle_table.particles[i].active) { + particle_update(&particle_table.particles[i]); + } + } +} + +void +particle_update(struct Particle *particle) +{ + particle->life -= 1; + /* boom */ + const struct Vec2 level_dim = level_get_dim(); + if (particle->life < 0) { + particle_destroy(particle); + } +} + +void +particle_table_draw(int timer) +{ + for (int i = 0; i < MAX_PARTICLES; ++i) { + if (particle_table.particles[i].active) { + particle_draw(&particle_table.particles[i], timer); + } + } +} + +void +particle_draw(struct Particle *particle, int timer) +{ + LZY_DrawTile(particle->id + 1, particle->pos.x, particle->pos.y); +} + +void +particle_destroy(struct Particle *particle) +{ + particle->active = 0; + --particle_table.n; +} + +int +particle_nb(void) +{ + return particle_table.n; +} diff --git a/src/player.c b/src/player.c new file mode 100644 index 0000000..f23a4ed --- /dev/null +++ b/src/player.c @@ -0,0 +1,290 @@ +#include "player.h" +#include "attack.h" +#include "level.h" +#include "conf.h" +#include "tools.h" +#include "lzy.h" +#include "particle.h" + +static struct Player player; +static void player_move(struct Vec2 spd); +static struct Vec2 player_update_rem(); +static int player_collide_pixel(int x, int y, tile_t id); +static int player_collide(int x, int y, tile_t id, int h); +static void player_attack(int x, int y, int type); +static void player_cooldown_update(); +static int jump_pressed; + +void +player_init(int chara) +{ + player.pos = (struct Vec2){84, 96}; + player.spd = (struct FVec2){0.0f, 0.0f}; + player.rem = (struct FVec2){0.0f, 0.0f}; + player.dir = (struct Vec2){1, 0}; + player.cooldown = (struct Cooldown){0, 0, 0, 0}; + player.attack = 0; + player.last_attack = 0; + player.life = 0; + player.id = chara; + player.djump = 0; +} + +void +player_update(void) +{ + const int on_ground = player_collide(player.pos.x, player.pos.y + 5, 1, 4); + if(on_ground) player.djump = 1; + + const struct Vec2 level_dim = level_get_dim(); + + const struct Vec2 dir = {LZY_KeyDown(LZYK_RIGHT) - LZY_KeyDown(LZYK_LEFT), + LZY_KeyDown(LZYK_DOWN) - LZY_KeyDown(LZYK_UP)}; + + player.spd.x *= (1 - PLAYER_FRIC); + player.spd.x += dir.x * PLAYER_ACC; + player.spd.y += GRAVITY * (player.last_attack == 4 && player.id == 1 ? -1 : 1); + + /* direction */ + if (dir.y) { + player.dir.y = dir.y; + } + if (dir.x) { + player.dir.x = dir.x; + } + + if (LZY_KeyDown(LZYK_O)) { + if(on_ground) { + player.spd.y = -JUMP_H; + jump_pressed = 1; + } + else if(player.djump && !jump_pressed) { + player.spd.y = -JUMP_H; + player.djump = 0; + particle_new(player.pos.x + PLAYER_W / 2, player.pos.y + PLAYER_H, 10, 5); + } + } + + if (jump_pressed && !LZY_KeyDown(LZYK_O)) { + jump_pressed = 0; + } + + if (player_collide(player.pos.x, player.pos.y + 5, 176, 4)) { + player.spd.y = -16; + } + + if (player_collide(player.pos.x, player.pos.y + 5, 153, 4)) { + player.spd.y = -3 * 5 * (player.life > 50 ? (float)player.life / 100 + 0.5 : 1); + player.spd.x = -player.dir.x * 5 * (player.life > 50 ? (float)player.life / 100 + 0.5 : 1); + player.life += 10; + } + + player_move(player_update_rem()); + + /* defining the direction of the shoot */ + const struct Vec2 shoot = { + (dir.x || dir.y) ? dir.x : player.dir.x, + (dir.x || dir.y) ? dir.y : player.dir.y + }; + + if (LZY_KeyDown(LZYK_X) && !player.last_attack) { + player_attack(player.pos.x, player.pos.y, 1); + } + + if (!LZY_KeyDown(LZYK_X)) { + player.last_attack = 0; + } + + player_cooldown_update(); + + if(player.pos.x > level_dim.x * TILE_S + 48 || player.pos.x < -72 || + player.pos.y > level_dim.y * TILE_S + 48 || player.pos.y < -96) { + player_init(player.id); + } +} + +static void player_attack(int x, int y, int type) { + const int up = LZY_KeyDown(LZYK_UP); + const int down = LZY_KeyDown(LZYK_DOWN); + const int left = LZY_KeyDown(LZYK_LEFT); + const int right = LZY_KeyDown(LZYK_RIGHT); + if(down && !player.cooldown.down) { + player.cooldown.down = attack(x + PLAYER_W / 2, + y + PLAYER_H / 2 + 12, player.dir.x, 1, 2 + player.id * 4); + player.attack = 2; + player.last_attack = 2; + return; + } + if(up && !player.cooldown.up) { + player.cooldown.up = attack(x + PLAYER_W / 2, + y + PLAYER_H / 2 - 12, player.dir.x, 1, 3 + player.id * 4); + player.attack = 3; + player.last_attack = 3; + return; + } + if((left || right) && !player.cooldown.side) { + player.cooldown.side = attack(x + PLAYER_W / 2 + player.dir.x * 12, + y + PLAYER_H / 2, player.dir.x, 1, 1 + player.id * 4); + player.attack = 1; + player.last_attack = 1; + return; + } + if(!(up || down || left || right) && !player.cooldown.neutral) { + player.cooldown.neutral = attack(x + PLAYER_W / 2, + y + PLAYER_H / 2, player.dir.x, 1, 4 + player.id * 4); + player.attack = 4; + player.last_attack = 4; + } +} + +static struct Vec2 +player_update_rem(void) +{ + struct FVec2 spdrem = (struct FVec2){player.spd.x + player.rem.x, + player.spd.y + player.rem.y}; + struct Vec2 ispd = (struct Vec2){spdrem.x, spdrem.y}; + + player.rem.x = spdrem.x - (float)ispd.x; + player.rem.y = spdrem.y - (float)ispd.y; + return ispd; +} + +static void +player_move(struct Vec2 spd) +{ + if (player_collide(player.pos.x, player.pos.y, 1, 4)) { + return; + } + + int coll_shift = 0; + + const int sign_x = sign(spd.x); + if (sign_x) {player.dir.x = sign_x;} + + if (spd.x) { + player.pos.x += spd.x; + + if (player_collide(player.pos.x, player.pos.y, 1, 1)) { + for(float i = 0.1f; i < 4; i+= 0.1) { + if(!player_collide(player.pos.x, player.pos.y + i, 1, 1)) { + player.pos.y += i; + coll_shift = 1; + break; + } + if(!player_collide(player.pos.x, player.pos.y - i, 1, 1)) { + player.pos.y -= i; + coll_shift = 1; + break; + } + } + } + + if(player_collide(player.pos.x, player.pos.y, 1, 1)) { + player.spd.x = 0.0f; + player.rem.x = 0.0f; + while (player_collide(player.pos.x, player.pos.y, 1, 1)) { + player.pos.x -= sign_x; + } + } + } + + const int sign_y = sign(spd.y); + if (sign_y) {player.dir.y = sign_y;} + + if (spd.y && !coll_shift) { + player.pos.y += spd.y; + + if (player_collide(player.pos.x, player.pos.y, 1, 1)) { + for(float i = 0.1f; i < 4; i += 0.1) { + if(!player_collide(player.pos.x + i, player.pos.y, 1, 1)) { + player.pos.x += i; + break; + } + if(!player_collide(player.pos.x - i, player.pos.y, 1, 1)) { + player.pos.x -= i; + break; + } + } + } + + if(player_collide(player.pos.x, player.pos.y, 1, 1)) { + player.spd.y = 0.0f; + player.rem.y = 0.0f; + while (player_collide(player.pos.x, player.pos.y, 1, 1)) { + player.pos.y -= sign_y; + } + } + } +} + +void +player_draw(int frame) +{ + if(player.attack) { + LZY_DrawTile(24 + TILESET_W * player.id + player.attack + (player.dir.x > 0 ? 0 : 1) * 6, + player.pos.x, player.pos.y); + } else { + if(LZY_KeyDown(LZYK_X)) { + LZY_DrawTile(24 + player.last_attack + TILESET_W * player.id + + (player.dir.x > 0 ? 0 : 1) * 6, + player.pos.x, player.pos.y); + } else { + LZY_DrawTile((frame % 30 > 15 ? 23 : 24) + TILESET_W * player.id + + (player.dir.x > 0 ? 0 : 1) * 6, + player.pos.x, player.pos.y); + } + } +} + +static int +player_collide_pixel(int x, int y, tile_t id) +{ + const tile_t tile = level_get_px(x, y); + + if (!tile) { + return 0; + } + + if (id == 1) { + return (tile) % TILESET_W; + } + + return tile == id; +} + +static int +player_collide(int x, int y, tile_t id, int h) +{ + + const struct Vec2 pos_tl = (struct Vec2){x + h, y + h}; + const struct Vec2 pos_br = + (struct Vec2){x + PLAYER_S - h - 1, y + PLAYER_S - h - 1}; + const struct Vec2 middle = + (struct Vec2){x + PLAYER_S / 2, y + PLAYER_S / 2}; + + if (player_collide_pixel(pos_tl.x, pos_tl.y, id) || + player_collide_pixel(pos_br.x, pos_br.y, id) || + player_collide_pixel(pos_tl.x, pos_br.y, id) || + player_collide_pixel(pos_br.x, pos_tl.y, id)) { + return 1; + } + return 0; +} + +void +player_reset_attack() { + player.attack = 0; +} + +void +player_cooldown_update() { + if (player.cooldown.up > 0) player.cooldown.up -= 1; + if (player.cooldown.down > 0) player.cooldown.down -= 1; + if (player.cooldown.side > 0) player.cooldown.side -= 1; + if (player.cooldown.neutral > 0) player.cooldown.neutral -= 1; +} + +int +player_get_life(void) { + return player.life; +} diff --git a/src/sandbag.c b/src/sandbag.c new file mode 100644 index 0000000..a286f1a --- /dev/null +++ b/src/sandbag.c @@ -0,0 +1,213 @@ +#include "sandbag.h" +#include "attack.h" +#include "level.h" +#include "conf.h" +#include "tools.h" +#include "lzy.h" +#include "particle.h" + +static struct Sandbag sandbag; +static void sandbag_move(struct Vec2 spd); +static struct Vec2 sandbag_update_rem(); +static int sandbag_collide_pixel(int x, int y, tile_t id); +static int sandbag_collide(int x, int y, tile_t id, int h); + +void +sandbag_init(void) +{ + sandbag.pos = (struct Vec2){300, 96}; + sandbag.spd = (struct FVec2){0.0f, 0.0f}; + sandbag.rem = (struct FVec2){0.0f, 0.0f}; + sandbag.dir = (struct Vec2){1, 0}; + sandbag.hitstun = 0; + sandbag.iced = 0; + sandbag.life = 0; + sandbag.active = 1; +} + +void +sandbag_update(int frame) +{ + const struct Vec2 level_dim = level_get_dim(); + + if(!sandbag.active) return; + const struct Attack *attack = attack_table_collide(sandbag.pos.x, sandbag.pos.y, 24, 24, 0); + if(attack != NULL) { + sandbag.spd.x = attack->dir.x * 5 * (sandbag.life > 50 ? (float)sandbag.life / 50 : 1); + sandbag.spd.y = -attack->dir.y * 5 * (sandbag.life > 50 ? (float)sandbag.life / 100 + 0.5 : 1); + if(!sandbag.hitstun) { + sandbag.life += attack->dam; + LZY_Sleep(10); + }; + sandbag.hitstun = 5; + if(attack->ice) {sandbag.iced = 30;} + } + + sandbag.spd.x *= (1 - AIR_FRIC) / (sandbag.iced ? 2 : 1); + sandbag.spd.y += GRAVITY; + + if (sandbag.spd.x) { + sandbag.dir.x = sign(sandbag.spd.x); + } + + sandbag_move(sandbag_update_rem()); + + if(sandbag.hitstun > 0) {sandbag.hitstun -= 1;} + if(sandbag.iced > 0) {sandbag.iced -= 1;} + if(sandbag.hitstun && frame % 2 && sandbag.life > 80) { + particle_new(sandbag.pos.x + 12, sandbag.pos.y + 12, 10 + rand() % 2, 5); + } + if(frame % 4 && sandbag.life > 120) { + particle_new(sandbag.pos.x + 12, sandbag.pos.y + 12, 12 + (frame % 8) / 2 % 2, 2); + } + + if(sandbag.pos.x > level_dim.x * TILE_S + 48 || sandbag.pos.x < -72 || + sandbag.pos.y > level_dim.y * TILE_S + 48 || sandbag.pos.y < -96) { + sandbag_init(); + } +} + +static struct Vec2 +sandbag_update_rem(void) +{ + struct FVec2 spdrem = (struct FVec2){sandbag.spd.x + sandbag.rem.x, + sandbag.spd.y + sandbag.rem.y}; + struct Vec2 ispd = (struct Vec2){spdrem.x, spdrem.y}; + + sandbag.rem.x = spdrem.x - (float)ispd.x; + sandbag.rem.y = spdrem.y - (float)ispd.y; + return ispd; +} + +static void +sandbag_move(struct Vec2 spd) +{ + if (sandbag_collide(sandbag.pos.x, sandbag.pos.y, 1, 4)) { + return; + } + + /* OOB */ + const struct Vec2 level_dim = level_get_dim(); + + int coll_shift = 0; + + const int sign_x = sign(spd.x); + if (sign_x) {sandbag.dir.x = sign_x;} + + if (spd.x) { + sandbag.pos.x += spd.x; + + if (sandbag_collide(sandbag.pos.x, sandbag.pos.y, 1, 1)) { + for(float i = 0.1f; i < 4; i+= 0.1) { + if(!sandbag_collide(sandbag.pos.x, sandbag.pos.y + i, 1, 1)) { + sandbag.pos.y += i; + coll_shift = 1; + break; + } + if(!sandbag_collide(sandbag.pos.x, sandbag.pos.y - i, 1, 1)) { + sandbag.pos.y -= i; + coll_shift = 1; + break; + } + } + } + + if(sandbag_collide(sandbag.pos.x, sandbag.pos.y, 1, 1)) { + if(abs(sandbag.spd.x) > 16) { + sandbag.spd.x = - sandbag.spd.x / 4; + } else { + sandbag.spd.x = 0.0f; + } + sandbag.rem.x = 0.0f; + while (sandbag_collide(sandbag.pos.x, sandbag.pos.y, 1, 1)) { + sandbag.pos.x -= sign_x; + } + } + } + + const int sign_y = sign(spd.y); + if (sign_y) {sandbag.dir.y = sign_y;} + + if (spd.y && !coll_shift) { + sandbag.pos.y += spd.y; + + if (sandbag_collide(sandbag.pos.x, sandbag.pos.y, 1, 1)) { + for(float i = 0.1f; i < 4; i += 0.1) { + if(!sandbag_collide(sandbag.pos.x + i, sandbag.pos.y, 1, 1)) { + sandbag.pos.x += i; + break; + } + if(!sandbag_collide(sandbag.pos.x - i, sandbag.pos.y, 1, 1)) { + sandbag.pos.x -= i; + break; + } + } + } + + if(sandbag_collide(sandbag.pos.x, sandbag.pos.y, 1, 1)) { + if(abs(sandbag.spd.y) > 16) { + sandbag.spd.y = - sandbag.spd.y / 4; + } else { + sandbag.spd.y = 0.0f; + } + sandbag.rem.y = 0.0f; + while (sandbag_collide(sandbag.pos.x, sandbag.pos.y, 1, 1)) { + sandbag.pos.y -= sign_y; + } + } + } +} + +void +sandbag_draw(int frame) +{ + if(!sandbag.active) return; + if(sandbag.hitstun) { + LZY_DrawTile(39, sandbag.pos.x, sandbag.pos.y); + } else { + LZY_DrawTile(38, sandbag.pos.x, sandbag.pos.y); + } + if(sandbag.iced > 0) { + LZY_DrawTile(16, sandbag.pos.x, sandbag.pos.y); + } +} + +static int +sandbag_collide_pixel(int x, int y, tile_t id) +{ + const tile_t tile = level_get_px(x, y); + + if (!tile) { + return 0; + } + + if (id == 1) { + return (tile) % TILESET_W; + } + + return tile == id; +} + +static int +sandbag_collide(int x, int y, tile_t id, int h) +{ + + const struct Vec2 pos_tl = (struct Vec2){x + h, y + h}; + const struct Vec2 pos_br = + (struct Vec2){x + PLAYER_S - h - 1, y + PLAYER_S - h - 1}; + const struct Vec2 middle = + (struct Vec2){x + PLAYER_S / 2, y + PLAYER_S / 2}; + + if (sandbag_collide_pixel(pos_tl.x, pos_tl.y, id) || + sandbag_collide_pixel(pos_br.x, pos_br.y, id) || + sandbag_collide_pixel(pos_tl.x, pos_br.y, id) || + sandbag_collide_pixel(pos_br.x, pos_tl.y, id)) { + return 1; + } + return 0; +} + +int +sandbag_get_life(void) { + return sandbag.life; +} diff --git a/src/tools.c b/src/tools.c new file mode 100644 index 0000000..25da409 --- /dev/null +++ b/src/tools.c @@ -0,0 +1,28 @@ +#include "tools.h" +#include "lzy.h" +#include +#include + +void +log_int(int x) +{ + char buf[64]; + sprintf(buf, "%d", x); + LZY_Log(buf); +} + +int +sign(int x) +{ + return (x > 0) - (x < 0); /* from jtmm2 */ +} + + +int +length(struct Vec2 *a, struct Vec2 *b) +{ + const int dist_x = abs(a->x - b->x); + const int dist_y = abs(a->y - b->y); + const float dist = sqrt(dist_x * dist_x + dist_y * dist_y); + return dist; +}