ksos edition

This commit is contained in:
Masséna Fezard | Nounouille 2022-04-04 08:16:10 +02:00
parent f006b6d58c
commit ff53f002f7
44 changed files with 2050 additions and 45 deletions

View File

@ -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)

View File

@ -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

26
inc/attack.h Normal file
View File

@ -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);

21
inc/bullet.h Normal file
View File

@ -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);

25
inc/conf.h Normal file
View File

@ -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

18
inc/level.h Normal file
View File

@ -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);

View File

@ -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 <gint/cpu.h>
#include <gint/clock.h>
#include <gint/display.h>
#include <gint/keyboard.h>
#include <gint/timer.h>
@ -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 */

7
inc/main.h Normal file
View File

@ -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

4
inc/overlay.h Normal file
View File

@ -0,0 +1,4 @@
#pragma once
void overlay_draw(int x, int y, int id, int life);

20
inc/particle.h Normal file
View File

@ -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);

22
inc/player.h Normal file
View File

@ -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);

16
inc/sandbag.h Normal file
View File

@ -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);

6
inc/tools.h Normal file
View File

@ -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);

12
inc/type.h Normal file
View File

@ -0,0 +1,12 @@
#pragma once
#include <stddef.h>
typedef int tile_t;
struct Vec2 {
int x, y;
};
struct FVec2 {
float x, y;
};

BIN
res/charas.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

BIN
res/delta.aseprite Normal file

Binary file not shown.

BIN
res/duck.aseprite Normal file

Binary file not shown.

BIN
res/export.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

BIN
res/export2.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -1,6 +1,8 @@
tset.png:
type: bopti-image
name: bimg_tset
profile: p8
font.png:
type: bopti-image
name: bimg_font
profile: p4

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1010 B

After

Width:  |  Height:  |  Size: 16 KiB

73
res/level.lua Normal file
View File

@ -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
}
}
}
}

20
res/level.tmx Normal file
View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.8" tiledversion="1.8.2" orientation="orthogonal" renderorder="right-down" width="17" height="10" tilewidth="24" tileheight="24" infinite="0" nextlayerid="2" nextobjectid="1">
<tileset firstgid="1" name="tset" tilewidth="24" tileheight="24" tilecount="69" columns="23">
<image source="tset.png" width="552" height="72"/>
</tileset>
<layer id="1" name="Tile Layer 1" width="17" height="10">
<data encoding="csv">
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,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
</data>
</layer>
</map>

73
res/level2.lua Normal file
View File

@ -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
}
}
}
}

103
res/level3.lua Normal file
View File

@ -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
}
}
}
}

BIN
res/poudingue.aseprite Normal file

Binary file not shown.

BIN
res/rdp.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

BIN
res/reveal.aseprite Normal file

Binary file not shown.

BIN
res/reveal2.aseprite Normal file

Binary file not shown.

BIN
res/reveal2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

BIN
res/reveal3.aseprite Normal file

Binary file not shown.

BIN
res/sakimi.aseprite Normal file

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 40 KiB

300
src/attack.c Normal file
View File

@ -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 <string.h>
#include <stdlib.h>
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;
}

101
src/bullet.c Normal file
View File

@ -0,0 +1,101 @@
#include "bullet.h"
#include "conf.h"
#include "tools.h"
#include "level.h"
#include "lzy.h"
#include <string.h>
#include <stdlib.h>
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;
}

235
src/level.c Normal file
View File

@ -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 <string.h>
#include <stdlib.h>
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;
}
}
}

View File

@ -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 <stdlib.h>
#include <math.h>
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);
}
}
}

14
src/overlay.c Normal file
View File

@ -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);
}

98
src/particle.c Normal file
View File

@ -0,0 +1,98 @@
#include "particle.h"
#include "conf.h"
#include "tools.h"
#include "level.h"
#include "lzy.h"
#include <string.h>
#include <stdlib.h>
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;
}

290
src/player.c Normal file
View File

@ -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;
}

213
src/sandbag.c Normal file
View File

@ -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;
}

28
src/tools.c Normal file
View File

@ -0,0 +1,28 @@
#include "tools.h"
#include "lzy.h"
#include <math.h>
#include <stdlib.h>
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;
}