diff options
| author | UnavailableDev <ggwildplay@gmail.com> | 2023-04-03 10:09:40 +0200 | 
|---|---|---|
| committer | UnavailableDev <ggwildplay@gmail.com> | 2023-04-03 10:09:40 +0200 | 
| commit | 05504df10934cac60b774fb10e86593ec3897510 (patch) | |
| tree | 89a418bb7477904f394e460d5e661c3047117030 /src/engine | |
| parent | 54c3e1139e3e0e328f7ce3e8a2a61b0bf530a772 (diff) | |
| parent | 0a014f39c375c0cf28de70ebaab6cb0a5266f3c2 (diff) | |
Merge branch 'dev' of https://github.com/UnavailableDev/avans-arcade into dev
Diffstat (limited to 'src/engine')
| -rw-r--r-- | src/engine/TODO/combat.h | 9 | ||||
| -rw-r--r-- | src/engine/bullet.c | 65 | ||||
| -rw-r--r-- | src/engine/bullet.h | 17 | ||||
| -rw-r--r-- | src/engine/camera.c | 38 | ||||
| -rw-r--r-- | src/engine/camera.h | 6 | ||||
| -rw-r--r-- | src/engine/draw_screen.c | 129 | ||||
| -rw-r--r-- | src/engine/draw_screen.h | 34 | ||||
| -rw-r--r-- | src/engine/engine.c | 4 | ||||
| -rw-r--r-- | src/engine/entity.c | 127 | ||||
| -rw-r--r-- | src/engine/entity.h | 82 | ||||
| -rw-r--r-- | src/engine/level.h | 5 | ||||
| -rw-r--r-- | src/engine/level_const.c | 37 | ||||
| -rw-r--r-- | src/engine/level_const.h | 31 | ||||
| -rw-r--r-- | src/engine/maths.c | 19 | ||||
| -rw-r--r-- | src/engine/maths.h | 22 | ||||
| -rw-r--r-- | src/engine/player_controller.c | 252 | ||||
| -rw-r--r-- | src/engine/player_controller.h | 7 | ||||
| -rw-r--r-- | src/engine/sprite_controller.c | 24 | ||||
| -rw-r--r-- | src/engine/sprite_controller.h | 118 | ||||
| -rw-r--r-- | src/engine/title_screen.c | 93 | ||||
| -rw-r--r-- | src/engine/title_screen.h | 3 | 
21 files changed, 1074 insertions, 48 deletions
| diff --git a/src/engine/TODO/combat.h b/src/engine/TODO/combat.h new file mode 100644 index 0000000..16c41f5 --- /dev/null +++ b/src/engine/TODO/combat.h @@ -0,0 +1,9 @@ +#include "hh_entity.h" + + +// attacktypes: + +/// @brief basic attack +/// @param dmg damage number +/// @param target entity under attack (damage changes this hp value) +void hh_attack_basic( int8_t dmg, hh_entity* target ); diff --git a/src/engine/bullet.c b/src/engine/bullet.c index 5aa9e51..e6ca6df 100644 --- a/src/engine/bullet.c +++ b/src/engine/bullet.c @@ -1,44 +1,35 @@  #include "bullet.h" -#include "engine/sprite_controller.h" -void shootBullet(vec2 playerPos, Bullet* bullet){ -	// Set bullet's x and y coordinates to player's coordinates -    bullet->x = playerPos.x; -    bullet->y = playerPos.y; -    // Set bullet's velocity to a fixed value -    bullet->velocity = 1; -    // Set bullet's status to active -    bullet->isActive = true; -} -void updateBullet(Bullet* bullet, int deltaTime){ -    // Only update bullet if it is active    -	 static int latestLocationBullet = 0; -    if (bullet->isActive) { -        // Move bullet based on velocity and deltaTime -        bullet->x += bullet->velocity * deltaTime; -		drawBullet(bullet); -        // Check if bullet has moved 16 pixels -        if (bullet->x - latestLocationBullet > 32) { -            // Set bullet's status to inactive -            bullet->isActive = false; -            drawBullet(&(Bullet){.x = -16,.y = -16.    }); -        } -    } -	 else{ -		latestLocationBullet = bullet->x; -	 } + +// TODO: use hh_entity as bullet struct +void hh_shoot_bullet(vec2 player, vec_cor cam_pos, hh_entity* bullet){ +	vec2 temp; +	if(g_hh_controller_p1.button_secondary){ +		if(bullet->is_grounded){ +			bullet->is_grounded=false; +			bullet->pos = player; +		} +	} +	else{ +		if(!bullet->is_grounded){ +			hh_update_bullet(bullet , cam_pos); +			hh_draw_bullet(*bullet); +		} +	} +	 +  } -void drawBullet(Bullet* bullet){ +void hh_update_bullet(hh_entity* bullet, vec_cor cam_pos){ +	bullet->pos.x += 1; -	hh_ppu_update_foreground(10, (hh_s_ppu_loc_fam_entry) -			{ -                .position_x = bullet->x, -                .position_y = bullet->y, -				.horizontal_flip = false, -				.vertical_flip = false, -				.palette_index = 7, -				.tilemap_index = 84, // change tilemap to the correct foreground index; -			}); +	// update bullet sprite on ppu +	bullet->render.fam.position_x = (bullet->pos.x-cam_pos.x); +	bullet->render.fam.position_y = (bullet->pos.y-cam_pos.y); + +} +void hh_draw_bullet(hh_entity bullet){ +	hh_s_ppu_loc_fam_entry temp = bullet.render.fam; +	hh_ppu_update_foreground(10,temp);  } diff --git a/src/engine/bullet.h b/src/engine/bullet.h index ad67d84..5f07b2e 100644 --- a/src/engine/bullet.h +++ b/src/engine/bullet.h @@ -1,16 +1,11 @@  #pragma once  #include "player_controller.h" +#include "engine/sprite_controller.h" +#include "input.h" -typedef struct { -    int x; -    int y; -    int velocity; -    int isActive; -    int hit; -} Bullet; +void hh_shoot_bullet(vec2 playerPos, vec_cor cam_pos, hh_entity*); -//Bullet* createBullet(float x, float y, float velocity, float direction); -void shootBullet(vec2 playerPos, Bullet* bullet); -void updateBullet(Bullet* bullet, int deltaTime); -void drawBullet(Bullet* bullet); +void hh_update_bullet(hh_entity* , vec_cor ); + +void hh_draw_bullet(hh_entity); diff --git a/src/engine/camera.c b/src/engine/camera.c new file mode 100644 index 0000000..6898430 --- /dev/null +++ b/src/engine/camera.c @@ -0,0 +1,38 @@ +#include "engine/camera.h" + +#include "ppu/consts.h" + + +vec_cor hh_update_camera(vec_cen new, vec2 min, vec2 max){ +	//TODO: change floating point math to fix point math +	//TODO: remove magic number at y camera offset + +	// new = vec_cen2cor(new,(vec2){.x=max.x/2,.y=max.y/2}); +	new = vec_cen2cor((vec2){.x=new.x+(HH_PPU_SPRITE_WIDTH),.y=new.y+(HH_PPU_SPRITE_HEIGHT*8)},(vec2){.x=(max.x	- min.x)/2,.y=(max.y	- min.y)/2}); +	// new = vec_cen2cor((vec2){.x=new.x+(HH_PPU_SPRITE_WIDTH),.y=new.y+(HH_PPU_SPRITE_HEIGHT*8)},(vec2){.x=max.x/2,.y=max.y/2}); + +	// new.x = new.x << HH_MATH_FIXED_POINT; +	// new.y = new.y << HH_MATH_FIXED_POINT; +	static vec_cor old; +	// old.x = old.x << HH_MATH_FIXED_POINT; +	// old.y = old.y << HH_MATH_FIXED_POINT; + +	// int16_t some = 0; +	// some = some <<= HH_MATH_FIXED_POINT-1; + +	// Camera smoothing +	new.x = (int)((float)new.x*0.1f + (float)old.x*0.9f); +	new.y = (int)((float)new.y*0.1f + (float)old.y*0.9f); + +	// old.x = old.x >> HH_MATH_FIXED_POINT; +	// old.y = old.y >> HH_MATH_FIXED_POINT; + + +	old.x = CLAMP(new.x,min.x,max.x); +	old.y = CLAMP(new.y,min.y,max.y); + +	//printf("camera new %d min %d max %d\n",new.y,min.y,max.y); +	return old; +} + + diff --git a/src/engine/camera.h b/src/engine/camera.h new file mode 100644 index 0000000..b3ffb52 --- /dev/null +++ b/src/engine/camera.h @@ -0,0 +1,6 @@ +#pragma once + +#include "engine/maths.h" + +vec_cor hh_update_camera(vec_cor new, vec2 min, vec2 max); + diff --git a/src/engine/draw_screen.c b/src/engine/draw_screen.c new file mode 100644 index 0000000..d1d7a04 --- /dev/null +++ b/src/engine/draw_screen.c @@ -0,0 +1,129 @@ +#include "engine/draw_screen.h" + +hh_level_entity level; +uint64_t offsetY=0; +uint64_t offsetX=0; +uint8_t hh_world_to_tile(vec2 pos){ +	 +	int index = (((pos.y/HH_PPU_SPRITE_HEIGHT)*level.size.x) + (pos.x/HH_PPU_SPRITE_WIDTH));//TODO: remove magic number(s) +	int tile= level.place[index]; +	return tile; +} + +void hh_update_screen(vec2 view, vec2 player){ +	int current_tile_y = view.y / HH_PPU_SPRITE_HEIGHT; +	int current_tile_x = view.x / HH_PPU_SPRITE_WIDTH; +	int offset_py = view.y - (offsetY / 40 * HH_PPU_SPRITE_HEIGHT); +	int offset_px = view.x - offsetX * HH_PPU_SPRITE_WIDTH; +	static int prev_ofsset = 0; + +	int size = MIN(HH_PPU_BG_CANVAS_TILES_H,level.size.x) * MIN(HH_PPU_BG_CANVAS_TILES_V,level.size.y); +	if( (offset_py == 0 || offset_py > 230) && level.size.y > level.size.x && prev_ofsset != offset_py){ +		if(offset_py==0){ +			offsetY = (current_tile_y-14) * level.size.x; +		} +		else{ +			offsetY = current_tile_y * level.size.x; +		} + +		// Update the background screen +		for (int BAM_index = 0; BAM_index < size; BAM_index++) { +			hh_ppu_update_background(BAM_index, (hh_s_ppu_loc_bam_entry){ +				.horizontal_flip = false, +				.vertical_flip = false, +				.palette_index = hh_get_palette(level.place[offsetY + BAM_index]), +				.tilemap_index = level.place[offsetY + BAM_index], +			}); +		} +		prev_ofsset = offset_py; +	} +	else if ((offset_px == 0 || offset_px > 310) && level.size.x > level.size.y && prev_ofsset != offset_px) +	{ +		if(offset_px==0){ +			offsetX = current_tile_x - 14; +		} +		else{ +			offsetX = current_tile_x; +		} +		// Update the background screen +		for (int BAM_index = 0; BAM_index < size; BAM_index++) { +			int var = (BAM_index / HH_PPU_BG_CANVAS_TILES_H) * level.size.x + MIN((BAM_index % HH_PPU_BG_CANVAS_TILES_H + offsetX),level.size.x); +			hh_ppu_update_background(BAM_index, (hh_s_ppu_loc_bam_entry){ +				.horizontal_flip = false, +				.vertical_flip = false, +				.palette_index = hh_get_palette(level.place[var]), +				.tilemap_index = level.place[var], +			}); +		} +	} + +	prev_ofsset = offset_px; +	 +} +void hh_setup_screen(hh_level_entity currentlevel){ +	hh_clear_screen(); +	hh_clear_sprite(); +	level = currentlevel; +	offsetY=0; +	offsetX=0; +	int size = MIN(HH_PPU_BG_CANVAS_TILES_H, level.size.x) * MIN(HH_PPU_BG_CANVAS_TILES_V, level.size.y); +	for (int BAM_index = 0; BAM_index < size; BAM_index++) { +		int var = (BAM_index / HH_PPU_BG_CANVAS_TILES_H) * level.size.x + BAM_index % HH_PPU_BG_CANVAS_TILES_H; +		hh_ppu_update_background(BAM_index, (hh_s_ppu_loc_bam_entry){ +			.horizontal_flip = false, +			.vertical_flip   = false, +			.palette_index   = hh_get_palette(currentlevel.place[var]), +			.tilemap_index   = currentlevel.place[var], +		}); +	} +} +vec_cor hh_draw_screen(vec2 player) { +   static vec_cor previousViewport = {0, 0}; +	int offset_py = offsetY / 40 * HH_PPU_SPRITE_HEIGHT; +	 +	int offset_px = (offsetX * HH_PPU_SPRITE_WIDTH) ; +	vec_cor viewport = hh_update_camera(player,(vec2){.x = offset_px, .y = offset_py},(vec2){.x = HH_PPU_SCREEN_WIDTH + offset_px, .y = 480 + offset_py});//TODO: remove magic number(s) +	viewport.x = CLAMP(viewport.x, 0, level.size.x * HH_PPU_SPRITE_WIDTH - HH_PPU_SCREEN_WIDTH); +	viewport.y = CLAMP(viewport.y, 0, level.size.y * HH_PPU_SPRITE_HEIGHT - HH_PPU_SCREEN_HEIGHT); +	 +	hh_update_screen((vec2){.y=viewport.y,.x=viewport.x},player); +   if (viewport.x == previousViewport.x && viewport.y == previousViewport.y){} +	else{ +		hh_ppu_update_aux((hh_s_ppu_loc_aux){ +			.bg_shift_x = viewport.x - offset_px, +			.bg_shift_y = viewport.y - offset_py, +			.fg_fetch	= 0, +			.sysreset	= 0, +		}); +		previousViewport = viewport; +	} + +	return viewport; +} + +void hh_clear_screen(){ +	// (HH_PPU_SCREEN_HEIGHT*HH_PPU_SCREEN_WIDTH)/(HH_PPU_SPRITE_HEIGHT*HH_PPU_SPRITE_WIDTH) +	for (int i = 0; i < HH_PPU_BG_CANVAS_TILES_H*HH_PPU_BG_CANVAS_TILES_V; i++) { +		hh_s_ppu_loc_bam_entry temp = { +			.vertical_flip=false,.horizontal_flip = false, +			.palette_index = 3,.tilemap_index = 0 +		}; +		hh_ppu_update_background(i,temp); +		hh_ppu_update_color(3,0,(hh_ppu_rgb_color_t){0x0,0x0,0x0}); +	} +	hh_ppu_update_aux((hh_s_ppu_loc_aux){ +		.bg_shift_x = 0, +		.bg_shift_y = 0, +		.fg_fetch	= 0, +		.sysreset	= 0, +	}); +} + +void hh_clear_sprite(){ +	for (int i = 0; i < HH_PPU_FG_SPRITE_COUNT; i++) { +		hh_ppu_update_foreground(i,(hh_s_ppu_loc_fam_entry){ +			.position_x = -HH_PPU_SPRITE_WIDTH, +			.position_y = -HH_PPU_SPRITE_HEIGHT, +		}); +	} +} diff --git a/src/engine/draw_screen.h b/src/engine/draw_screen.h new file mode 100644 index 0000000..9130842 --- /dev/null +++ b/src/engine/draw_screen.h @@ -0,0 +1,34 @@ +#pragma once + + +// every function call for drawing the screen goes here. +#include "engine/maths.h" +#include "ppu/ppu.h" +#include "engine/level_const.h" +#include "engine/sprite_controller.h" +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include "engine/camera.h" + +#define hh_max_x_size 40  +#define hh_max_y_size 30 + +/** @brief return a single tile from world binary */ +uint8_t hh_world_to_tile(vec2 pos); + +/** @brief shift to level if viewport changed position */ +vec_cor hh_draw_screen(vec2 player); + +/** @brief send data to BAM memory from binary level */ +void hh_setup_screen(hh_level_entity currentlevel); +/** @brief updates screen based on view and maybe player position if it needs to turn back*/ +void hh_update_screen(vec2 view, vec2 ); + +/** @brief send black screen to background memory */ +void hh_clear_screen(); + +/** @brief clears all sprite data */ +void hh_clear_sprite(); +/** @brief send data to BAM memory from binary from shop */ +void hh_setup_Shop(); diff --git a/src/engine/engine.c b/src/engine/engine.c new file mode 100644 index 0000000..799ee7c --- /dev/null +++ b/src/engine/engine.c @@ -0,0 +1,4 @@ +#include "engine/draw_screen.h" +#include "engine/level.h" +#include "engine/maths.h" +#include "engine/sprite_controller.h" diff --git a/src/engine/entity.c b/src/engine/entity.c new file mode 100644 index 0000000..535759d --- /dev/null +++ b/src/engine/entity.c @@ -0,0 +1,127 @@ +#include <stdbool.h> + +#include "engine/entity.h" +#include "engine/maths.h" + +/* +    PLAYER: (pos on X) +    ,___, +    |   | +    | X | +    |___| + +*/ + +bool hh_collision(vec_cor pos1, vec2 pos2){ +    if (pos2.x == CLAMP(pos2.x, pos1.x, pos1.x+16)){// hit x +        return true; +    } + +    if (pos2.y == CLAMP(pos2.y, pos1.y, pos1.y+16)){// hit y +        return true; +    } +    return false; +} + +void hh_solve_collision(vec2 pos_environment, hh_entity* entity){ +	if (!hh_collision(pos_environment,entity->pos)) +		return; + +	printf("BONK!/n"); +	// if (entity->vel.y > 0){ +	// 	entity->pos.y = MAX(entity->pos.y,pos_environment.y); +	// 	entity->vel.y = 0; +	// } else { +	// 	entity->pos.y = MIN(entity->pos.y,pos_environment.y); +	// 	entity->vel.y = 0; +	// } +	// if (entity->vel.x <= 0){ +	// 	entity->pos.x = MIN(entity->pos.x,pos_environment.x-16); +	// 	entity->vel.x = 0; +	// } else { +	// 	entity->pos.x = MAX(entity->pos.x,pos_environment.x+16); +	// 	entity->vel.x = 0; +	// }  +} +hh_entity hh_background_collision (hh_entity temp_old_entity,hh_entity temp_new_entity){ + +		temp_old_entity.is_grounded = false; +  +// solves x collision +	if (temp_old_entity.vel.x <= 0) { +		if (hh_colidable(hh_world_to_tile((vec2){.x=temp_new_entity.pos.x + 0, .y=temp_old_entity.pos.y + 0})) ||  +			hh_colidable(hh_world_to_tile((vec2){.x=temp_new_entity.pos.x + 0, .y=temp_old_entity.pos.y + 15}))) { +			temp_new_entity.pos.x = (temp_new_entity.pos.x & ~15) + 16, +			temp_new_entity.vel.x = 0; +		} +	} else { +		if (hh_colidable(hh_world_to_tile((vec2){.x=temp_new_entity.pos.x + 16, .y=temp_old_entity.pos.y + 0})) ||  +			hh_colidable(hh_world_to_tile((vec2){.x=temp_new_entity.pos.x + 16, .y=temp_old_entity.pos.y + 15}))) { +			temp_new_entity.pos.x = temp_new_entity.pos.x & ~15, // <-- magic comma, NOT TOUCHY +			temp_new_entity.vel.x = 0; +		} +	} + +	//solves y collision +	if (temp_old_entity.vel.y <= 0) { +		if (hh_colidable(hh_world_to_tile((vec2){.x=temp_new_entity.pos.x + 0, .y=temp_new_entity.pos.y + 0})) ||  +			hh_colidable(hh_world_to_tile((vec2){.x=temp_new_entity.pos.x + 15, .y=temp_new_entity.pos.y + 0}))) { +			temp_new_entity.pos.y = (temp_new_entity.pos.y & ~15) + 16, +			temp_new_entity.vel.y = 0; +		} +	} else { +		if (hh_colidable(hh_world_to_tile((vec2){.x=temp_new_entity.pos.x + 0, .y=temp_new_entity.pos.y + 15})) ||  +			hh_colidable(hh_world_to_tile((vec2){.x=temp_new_entity.pos.x + 15, .y=temp_new_entity.pos.y + 15}))) { +			temp_new_entity.pos.y = temp_new_entity.pos.y & ~15, +			temp_new_entity.vel.y = 0; +			temp_old_entity.is_grounded = true; +		} +	} +	temp_old_entity.pos = temp_new_entity.pos;  +	temp_old_entity.vel = temp_new_entity.vel; +	return temp_old_entity; +} + +hh_entity hh_enemy_collision(hh_entity temp_player, hh_entity temp_enemy){ +	 +	bool collide = hh_distance_circles( temp_player.pos,  temp_enemy.pos, temp_player.radius, temp_enemy.radius); + +	if (collide == true && temp_player.is_hit == false) +	{ +		temp_player.is_hit = true; +		//angle = atan2( tempEntity.pos_y - tempPlayer.pos_y, tempEntity.pos_x - tempPlayer.pos_x); +		if(temp_player.pos.x <= temp_enemy.pos.x) //player left of enemy -- creates flinch movement L or R +		{ +		//	printf("BONK-left!/n"); +			temp_player.vel.y = -5; +			temp_player.vel.x = -8; +		}	else { +		//	printf("BONK-right!/n"); +			temp_player.vel.y = -5; +			temp_player.vel.x = 8; +		} +		// ghost mode / invulnerable or other things on hit +		//	temp_player.hp--; +			 +	} else { +		temp_player.is_hit = false; +		 +	} + + +return temp_player; +} + + +bool hh_distance_circles (vec2 object_1, vec2 object_2, int radius_1, int radius_2){ +	int a_squared = (object_1.x - object_2.x) * (object_1.x - object_2.x); +	int b_squared = (object_1.y - object_2.y) * (object_1.y - object_2.y); +	int c_squared = a_squared + b_squared;  +	int radius = ( radius_1 + radius_2) * ( radius_1 + radius_2 ); + +		if( c_squared <= radius ){ +			return true; +		} else { +			return false; +		} +} diff --git a/src/engine/entity.h b/src/engine/entity.h new file mode 100644 index 0000000..cad6ba4 --- /dev/null +++ b/src/engine/entity.h @@ -0,0 +1,82 @@ +#pragma once + +#include <stdint.h> +#include <stdbool.h> +#include <stdio.h> + +#include "ppu/types.h" + +#include "engine/maths.h" + +typedef uint8_t hh_idx_t; + +typedef enum { +	fire, ice, poison +}hh_e_damage_t; + +typedef struct { +	hh_s_ppu_loc_fam_entry fam; //screen +	hh_idx_t frame0; +	hh_idx_t palette; +	 +}hh_s_rendering; + +typedef struct { +	int8_t hp; +	int8_t dmg; +	hh_e_damage_t dmg_type; +	int8_t speed_x, speed_y; + +} hh_s_atributes; + + +typedef struct { +    vec2 pos, vel, vec; +    bool is_grounded; +	 bool is_hit; +	 uint8_t radius; +    int8_t hp; +    int8_t speed; +	 hh_s_rendering render; +    //armor/block? +}hh_entity; + +typedef struct { +	hh_entity p; +	hh_s_atributes atr; +}hh_s_player; + + +/// @brief detect for collision enity and eviroment +/// @param pos1 position of environment tile to be checked +/// @param pos2 position entity +/// @return true if collision between enity and environment +bool hh_collision(vec2 pos1, vec2 pos2); + +/// @brief solve collisions +/// @param environment position +/// @param entity position +/// @return solved new entity position +void hh_solve_collision(vec2 pos_environment, hh_entity* entity); + +/// @brief solve collision of entity with background tiles +/// @param temp_old_entity old data of entity  +/// @param temp_new_entity new data of entity where it wants to go to +/// @return updated new entity where it actually can go to +hh_entity hh_background_collision (hh_entity temp_old_entity, hh_entity temp_new_entity); + +/// @brief solve collision of player with enemy  +/// @param temp_player data of player  +/// @param temp_enemy data of enemy +/// @return updated player with new stats if hitted with enemy +hh_entity hh_enemy_collision(hh_entity temp_player, hh_entity temp_enemy); + +/// @brief calculate if circles (entity) hit each other  +/// @param object_1 position of first object (entity) +/// @param object_2 position of second object (entity) +/// @param radius_1 radius of first object (entity) +/// @param radius_2 radius of second object (entity) +/// @return true if objects collids +bool hh_distance_circles (vec2 object_1, vec2 object_2, int radius_1, int radius_2); + + diff --git a/src/engine/level.h b/src/engine/level.h new file mode 100644 index 0000000..8d610dd --- /dev/null +++ b/src/engine/level.h @@ -0,0 +1,5 @@ +#pragma once +//deal with loading/saving the correct level + +/** @brief  */ +void hh_map_load(); diff --git a/src/engine/level_const.c b/src/engine/level_const.c new file mode 100644 index 0000000..5ba0187 --- /dev/null +++ b/src/engine/level_const.c @@ -0,0 +1,37 @@ +#include "engine/level_const.h" + + +hh_g_all_levels hh_init_game_levels(){ +	hh_g_all_levels levels; +	levels.current_level=0; +	 +	levels.level[0].size.x=40; +	levels.level[0].size.y=100; +	levels.level[0].hh_level_completed=false; + +	levels.level[1].size.x=100; +	levels.level[1].size.y=28; +	levels.level[1].hh_level_completed=false; + +	FILE *fp = fopen("../test/bin/level1_test.bin", "rb"); +	fseek(fp, 0, SEEK_END); +	int size = ftell(fp) / sizeof(int); +	fseek(fp, (0 * sizeof(int)) + sizeof(int), SEEK_SET); +	int* hh_game_level1 = malloc(size * sizeof(int)); +	fread(hh_game_level1, sizeof(int), size, fp); +	fclose(fp); + +	FILE *lvl2 = fopen("../test/bin/level2_test.bin", "rb"); +	fseek(lvl2, 0, SEEK_END); +	size = ftell(lvl2) / sizeof(int); +	fseek(lvl2, (0 * sizeof(int)) + sizeof(int), SEEK_SET); +	int* hh_game_level2 = malloc(size * sizeof(int)); +	fread(hh_game_level2, sizeof(int), size, lvl2); +	fclose(lvl2); + +	levels.level[0].place = hh_game_level1; +	levels.level[1].place = hh_game_level2; + +	return levels; +} + diff --git a/src/engine/level_const.h b/src/engine/level_const.h new file mode 100644 index 0000000..b86ae7b --- /dev/null +++ b/src/engine/level_const.h @@ -0,0 +1,31 @@ +#pragma once +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <stdbool.h> +#include "engine/maths.h" +#include "engine/entity.h" + +typedef enum { +	hh_e_state_starting_screen, +	hh_e_state_shop, +	hh_e_state_gameplay, +	hh_e_state_game_over, +	hh_e_state_high_score +} hh_e_game_state; +//entity array met enemeies +typedef struct  { +	vec2 size; +	int hh_total_enemies; +	int* place; +	bool hh_level_completed; +}hh_level_entity; + +typedef struct  { +	hh_level_entity level[2]; +	int current_level; + + +}hh_g_all_levels; + +hh_g_all_levels hh_init_game_levels(); diff --git a/src/engine/maths.c b/src/engine/maths.c new file mode 100644 index 0000000..475bba2 --- /dev/null +++ b/src/engine/maths.c @@ -0,0 +1,19 @@ +#include "engine/maths.h" + +vec2 vec_add(vec2 a, vec2 b){ +	return (vec2){a.x + b.x, a.y + b.y}; +} + +vec_cor vec_cen2cor(vec_cen in, vec2 halfDistance){ +	return (vec_cor){ +		.x = in.x - halfDistance.x, +		.y = in.y - halfDistance.y, +	}; +} + +vec_cen vec_cor2cen(vec_cor in, vec2 halfDistance){ +	return (vec_cen){ +		.x = in.x + halfDistance.x, +		.y = in.y + halfDistance.y, +	}; +} diff --git a/src/engine/maths.h b/src/engine/maths.h new file mode 100644 index 0000000..bef287e --- /dev/null +++ b/src/engine/maths.h @@ -0,0 +1,22 @@ +#pragma once +#include <stdint.h> +// #include <math.h> + +typedef struct { +	int32_t x,y; +} vec2; + +typedef vec2 vec_cen;//centered +typedef vec2 vec_cor;//left upper corner + +vec2 vec_add(vec2 a, vec2 b); + +vec_cor vec_cen2cor(vec_cen in, vec2 halfDistance); +vec_cor vec_cor2cen(vec_cen in, vec2 halfDistance); + +//fixed point at decimal 7lsb (world positions in pixels (with fixed decimal point)) +#define HH_MATH_FIXED_POINT 7 + +#define MIN(a,b) (((a)<(b))?(a):(b)) +#define MAX(a,b) (((a)>(b))?(a):(b)) +#define CLAMP(N,LOWER,UPPER) (MIN(MAX(LOWER, N), UPPER)) diff --git a/src/engine/player_controller.c b/src/engine/player_controller.c new file mode 100644 index 0000000..647b00c --- /dev/null +++ b/src/engine/player_controller.c @@ -0,0 +1,252 @@ +#include "ppu/types.h" +#include "engine/camera.h" +#include "engine/draw_screen.h" +#include "engine/sprite_controller.h" +#include "engine/player_controller.h" + +#include "input.h" + +#include "engine/bullet.h" +void hh_player_actions() { +	static Bullet bullet ={ +		.isActive=false, +	}; +	static hh_entity player={ +		.hp = 4, +		.speed = 6, +		.is_grounded = false, +		.is_hit = false, +		.radius = 8, +		.pos = (vec2){32,32}, +		.vel = (vec2){0,0}, +		.vec = (vec2){0,0}, +		.render = { +			.frame0 = 80, +			.palette = 3, +			.fam = (hh_s_ppu_loc_fam_entry){ +				.horizontal_flip = false, +				.vertical_flip = false, +				.palette_index = 2, +				.tilemap_index = 60, +			} +		} +	}, player_new = {0}; + + +	static hh_entity enemy={ +		.hp = 4, +		.speed = 6, +		.is_grounded = false, +		.is_hit = false, +		.radius = 8, +		.pos = (vec2){128,48}, +		.vel = (vec2){0,0}, +		.vec = (vec2){0,0}, +		.render = { +			.frame0 = 20, +			.palette = 7, +			.fam = (hh_s_ppu_loc_fam_entry){ +				.horizontal_flip = false, +				.vertical_flip = false, +				.palette_index = 7, +				.tilemap_index = 1, +			} +		} +	}; +	player_new = player; +	// hh_input_read(); +	static uint8_t hit = 0; +	int8_t hit_timer = 0; +	int8_t direction_x = (-1 * g_hh_controller_p1.dpad_left) + (1 * g_hh_controller_p1.dpad_right); +	int8_t direction_y = (-1 * g_hh_controller_p1.dpad_up) + (1 * g_hh_controller_p1.dpad_down); + +	if(player.is_hit == true){ +		hit_timer = 9; +		player.is_hit = false;	 +	}  +	if(hit_timer > -10){ +			hit_timer--; +	} + +	if(hit_timer <= 0){ +		if(direction_x != 0){ +			if(player.vel.x > -1 * player.speed && player.vel.x < player.speed) { +				player.vel.x = player.vel.x + direction_x; +			} else { +				if (player.vel.x > 0) { +					player.vel.x--; +				} else if(player.vel.x < 0) { +					player.vel.x++;  +				} +			} +		} else { +			if (player.vel.x > 0) { +				player.vel.x--; +			} else if(player.vel.x < 0) { +			player.vel.x++;  +			} +		} +		 +		/* // movement Y (w-s) disable gravity to use this +		if(direction_y != 0){ +			if(player.vel.y > -4 && player.vel.y < 4 ) { +				player.vel.y =  player.vel.y + direction_y; +			} +		} else { +			if (player.vel.y > 0) { +				player.vel.y--; +			} else if(player.vel.y < 0) { +				player.vel.y++;  +			} +		}		 +		 +		*/ +	} else { +		if (player.vel.x > 0) { +			player.vel.x--; +		} else if(player.vel.x < 0) { +			player.vel.x++;  +		} +			player.vel.y++; +	} +	 + +	if (g_hh_controller_p1.button_primary && player.is_grounded == true) {//JUMP +	 	player.vel.y = -10; +		player.is_grounded = false; +	} else if (player.vel.y < 6){ +		 player.vel.y += 1; //gravity +	} + +	if(g_hh_controller_p1.button_secondary==true){ +		shootBullet(player.pos,&bullet); +	} +	updateBullet(&bullet,5); + + +	 +/* +	player.vel = (vec2){.x = (-1 * g_hh_controller_p1.dpad_left) + (1 * g_hh_controller_p1.dpad_right), +	.y = (-1 * g_hh_controller_p1.dpad_up) + (1 * g_hh_controller_p1.dpad_down) }; + +		player_new.vel = (vec2){ +		.x = player.vel.x, +		.y = player.vel.y, +	}; +*/ + +		player_new.vel = (vec2){ +		.x = player.vel.x, +		.y = player.vel.y, +	}; + +		player_new = hh_enemy_collision(player, enemy); +	 +	 +	// const int8_t maa = 3; +	// const int8_t mbb = -3; +	// if (g_hh_controller_p1.dpad_up) +	// +	// if (g_hh_controller_p1.dpad_down) +	// +	// if (g_hh_controller_p1.dpad_left) { +	// 	player.vel.x += mbb; +	// 	// g_hh_demo_balls[0].horizontal_flip = true; +	// } +	// if (g_hh_controller_p1.dpad_right) { +	// 	player.vel.x += maa; +	// 	// g_hh_demo_balls[0].horizontal_flip = true; +	// } +	// if (g_hh_controller_p1.button_primary /*&& player.is_grounded*/) //JUMP +	// 	player.vel.y += -6; +	// // // if (g_hh_controller_p1.button_secondary) + +	// player.vel.y += 1; //gravity + + +	//END OF VECTOR CHANGES +	// player.vel.y = CLAMP(player.vel.y,-32,32); +	// player.vel.x = CLAMP(player.vel.x,-32,32); + +	player_new.pos = (vec2){ +		.x = player.pos.x + player_new.vel.x, +		.y = player.pos.y + player_new.vel.y, +	}; + + + +	// const uint8_t empty = 0; +	// hh_s_tiles tiles[9]; +	// const vec2 tile_offset[9] = { +	// 	(vec2){-16,-16},(vec2){0,-16},(vec2){+16,-16}, +	// 	(vec2){-16,0},  (vec2){0,0},  (vec2){+16,0}, +	// 	(vec2){-16,+16},(vec2){0,+16},(vec2){+16,+16}, +	// }; +	// for (int i = 0; i < 9; i++) { +	// 	vec2 temp_pos = vec_add(player.pos, tile_offset[i]); +	// 	temp_pos =(vec2){ +	// 		.x = temp_pos.x, +	// 		.y = temp_pos.y, +	// 	}; +	// 	hh_s_tiles tile = { +	// 		.pos = temp_pos, +	// 		.idx = hh_world_to_tile(temp_pos) +	// 	}; +	// 	if(hh_colidable(tile.idx)) { +	// 		tiles[i]=tile; +	// 		// printf(" collidable near!"); +	// 	} else { +	// 		tiles[i].idx = 0; +	// 	} +	// } +	/* +	012 +	345 +	678 +	*/ +	// for (int i = 0; i < 9; i++) +	// { +	// 	if (tiles[i].idx != 0){ +	// 		hh_solve_collision(tiles[i].pos, &player); +	// 	} +	// } + +	player =  hh_background_collision ( player, player_new); +	 +	//player = player_new; + +	vec_cor cam_pos;//value in tiles +	// cam_pos = (vec2){0,0}; +	cam_pos = hh_update_camera(player.pos,(vec2){0,0},(vec2){.x=20*16,.y=30*16});//TODO: remove magic number(s) +	// printf("%i, %i:%i, %i\n",player.pos.x,player.pos.y,cam_pos.x,cam_pos.y); +	hh_draw_screen(cam_pos); +	// update player sprite on ppu +	player.render.fam.position_x = (player.pos.x-cam_pos.x); +	player.render.fam.position_y = (player.pos.y-cam_pos.y); + +	enemy.render.fam.position_x = (enemy.pos.x-cam_pos.x); +	enemy.render.fam.position_y = (enemy.pos.y-cam_pos.y); + +	player.render.fam.tilemap_index = 2;//TODO: these two lines should be redundant +	player.render.fam.palette_index = 7; +	// hh_ppu_update_foreground(0, player.render.fam); + +	for (int i = 0; i < 4; i++) +	{ +		hh_s_ppu_loc_fam_entry temp = player.render.fam; +		temp.position_x = player.render.fam.position_x+(!(player.vel.x>0)?-1:1)*(i%2?8:-8); +		temp.position_y = player.render.fam.position_y+(i>1?0:-16); +		temp.tilemap_index = player.render.frame0 + i; +		temp.palette_index = player.render.palette; +		temp.horizontal_flip = !(player.vel.x>0); +		hh_ppu_update_foreground(i,temp); +	} +	 + + +	hh_ppu_update_foreground(4, enemy.render.fam); + +} + + + diff --git a/src/engine/player_controller.h b/src/engine/player_controller.h new file mode 100644 index 0000000..400c18e --- /dev/null +++ b/src/engine/player_controller.h @@ -0,0 +1,7 @@ +#pragma once + +#include "engine/maths.h" +#include "engine/entity.h" +// inputs + +void hh_player_actions(); diff --git a/src/engine/sprite_controller.c b/src/engine/sprite_controller.c new file mode 100644 index 0000000..b38b647 --- /dev/null +++ b/src/engine/sprite_controller.c @@ -0,0 +1,24 @@ +#include <stdint.h> + +#include "engine/sprite_controller.h" +#include "ppu/types.h" +#include "ppu/consts.h" +#include "ppu/ppu.h" + +uint8_t hh_get_palette(uint8_t tile_idx) { +	return hh_g_sprite_palette[tile_idx]; +} + +void hh_setup_palettes(){ +	//TODO: use simpler function +	for (int idx = 0; idx < HH_PPU_PALETTE_COUNT; idx++) { +		for (int col = 0; col < HH_PPU_PALETTE_COLOR_COUNT; col++) { +			hh_ppu_update_color(idx,col,hh_g_palette[idx][col]); +		} +	} +	// hh_ppu_update_palette_table(hh_g_palette); +} + +bool hh_colidable(uint8_t tile_idx){ +	return (hh_get_palette(tile_idx) != 0); +} diff --git a/src/engine/sprite_controller.h b/src/engine/sprite_controller.h new file mode 100644 index 0000000..fc6d3d3 --- /dev/null +++ b/src/engine/sprite_controller.h @@ -0,0 +1,118 @@ +#pragma once +#include <stdint.h> + +#include "ppu/types.h" + +// handles sprites + +// Bg sprites + +// Fg or entity sprites + +//TODO: pack data inside of sprite_palette LUT +//HH_PPU_PALETTE_COUNT +#define HH_SPRITE_COUNT 80 +#define HH_PAL_IDX_SKY 512 +#define HH_PAL_IDX_BRICK 1 +const static uint8_t hh_g_sprite_palette[HH_SPRITE_COUNT] = { +	//TODO: make a buffer of 16 no-collider sprites (instead of the current 1) +	0,1,1,1,1,1,1,1,1,1, //1+9 +	1,1,1,1,1,1,1,1,1,1, //6+4 +	1,1,1,1,1,1,1,1,1,	//9 +	7,7,7,2,7,7,1,2,7, +	7,7,7,7, //??  + +	7,6,6,6,6,6,6,6, //baskets +	7,7,7,7,7,7,7,7,7,7, //shop +	7,7,7,7,7, //shop +	6,6,6,6,6, //(hi-)score +	 +	3,3,3,3,3,3, //title_screen icon +	6,6,6,6,/*6,6,6,6,6,6, //title_screen large letters +	6,6,6,6,*/ +	//other palettes here: +	// [HH_PAL_IDX_SKY] = 0, +}; + + +const static hh_ppu_loc_palette_table_t hh_g_palette = { +	{//palette info here +		{0x1,0x2,0x3}, +		{0x0,0x0,0x0}, +		{0x0,0x0,0x0}, +		{0x0,0x0,0x0}, +		{0x0,0x0,0x0}, +		{0x0,0x0,0x0}, +		{0x0,0x0,0x0}, +		{0x0,0x0,0x0}}, +	{//Bricks +		{0x1,0x2,0x3},//01 +		{0xd,0x8,0xa},//24 +		{0x0,0x0,0x1},//25 +		{0x1,0x1,0x1},//26 +		{0x1,0x1,0x2},//27 +		{0x2,0x2,0x3},//28 +		{0x3,0x4,0x5},//29 +		{0x5,0x1,0x7}}, +	{//slime +		{0x1,0x2,0x3}, +		{0x1,0x3,0x2}, +		{0x4,0x8,0x3}, +		{0x7,0xa,0x4}, +		{0x0,0x0,0x0}, +		{0x0,0x0,0x0}, +		{0x0,0x0,0x0}, +		{0x0,0x0,0x0}}, +	{//player //TODO: use one less color && update player indexed sprites +		{0x0,0x0,0x0}, +		{0x1,0x1,0x1}, +		{0x4,0x2,0x5}, +		{0x7,0x3,0x7}, +		{0xe,0xe,0xe},  +		{0xe,0xe,0xe}, //elemental +		{0x0,0x0,0x0}, +		{0x0,0x0,0x0}}, +	{ +		{0x0,0x0,0x0}, +		{0x0,0x0,0x0}, +		{0x0,0x0,0x0}, +		{0x0,0x0,0x0}, +		{0x0,0x0,0x0}, +		{0x0,0x0,0x0}, +		{0x0,0x0,0x0}, +		{0x0,0x0,0x0}}, +	{//elemental +		{0x0,0x0,0x0}, +		{0x0,0x0,0x0}, +		{0x0,0x0,0x0}, +		{0x0,0x0,0x0}, +		{0x0,0x0,0x0}, +		{0x0,0x0,0x0}, +		{0x0,0x0,0x0}, +		{0x0,0x0,0x0}}, +	{//white +		{0x1,0x2,0x3}, +		{0xf,0xf,0xf}, +		{0xf,0xf,0xf}, +		{0xf,0xf,0xf}, +		{0xf,0xf,0xf}, +		{0xf,0xf,0xf}, +		{0xf,0xf,0xf}, +		{0xf,0xf,0xf}}, +	{//Dev palette (7) +		{0x0,0xf,0xf}, +		{0xf,0xf,0xf}, +		{0xf,0x0,0xf}, +		{0xf,0xf,0x0}, +		{0xf,0x0,0x0}, +		{0x0,0xf,0x0}, +		{0x0,0x0,0xf}, +		{0x0,0x0,0x0}} +}; + +void hh_setup_palettes(); + +/** @brief return palette index that belongs to tilemap index */ +uint8_t hh_get_palette(uint8_t tile_idx); + +bool hh_colidable(uint8_t tile_idx); diff --git a/src/engine/title_screen.c b/src/engine/title_screen.c new file mode 100644 index 0000000..9c7ed48 --- /dev/null +++ b/src/engine/title_screen.c @@ -0,0 +1,93 @@ +#include "ppu/ppu.h" +#include "ppu/types.h" +#include "ppu/consts.h" + + +#include "engine/draw_screen.h" +#include "engine/entity.h" + +void hh_init_title_screen(){ + +	// hh_clear_screen(); + +	//send data +	uint8_t idx = 0; +	const uint8_t tilemap_offset = 59; +	int tiles_h = HH_PPU_BG_CANVAS_TILES_H; +	int vp_h = HH_PPU_SCREEN_WIDTH/HH_PPU_SPRITE_WIDTH; //screen_h in tiles +	int vert_offset = tiles_h*3; + +	const uint8_t arr[4][4] = { +		{0,1,1,0}, +		{2,3,3,2}, +		{4,0,0,4}, +		{5,6,6,5}, +	}; +	int val, counter =0; +	hh_ppu_update_color(5, 0, (hh_ppu_rgb_color_t) {0x1, 0x1, 0x1}); +	for (int i = 0; i < 4; i++) { +		for (int j = 0; j < 4; j++) { +			val = arr[i][j]; + +			hh_s_ppu_loc_bam_entry temp = { +			.vertical_flip=false, .horizontal_flip = ((j % 4 < 2) ? false : true), +			.palette_index = (counter == 9 || counter == 10? 5:3), .tilemap_index = (val > 0 ? (tilemap_offset + val) : 0) +			}; + +			int vert_pos = tiles_h*i; +			int x_pos = j; +			idx = vert_offset + vert_pos + x_pos + vp_h/2-2; +			 +			hh_ppu_update_background(idx,temp); +			counter++; +		} + +	} +	 + +	const uint8_t letters_offset = 66; +	const int _size_hooded = 7, _size_v = 2; + +	// char* hh = "hooded"; +	int hooded_lookup[7][2]={ +		{0,1},{0,2},//H +		{3,4},{3,4},//oo +		{5,6},{13,9},//de +		{5,6}//d +	}; + +	counter = 8; +	for (int i = 0; i < _size_hooded; i++) { +		for (int vert = 1; vert <= _size_v; vert++) { +			//TODO: move 'H' a few pixels to the right for a more cohesive font spacing +			hh_ppu_update_foreground(counter++, (hh_s_ppu_loc_fam_entry) { +				.vertical_flip = false, .horizontal_flip = false, +				.palette_index = 6, .tilemap_index = letters_offset + hooded_lookup[i][vert-1], +				.position_x = (16*i + 64+48), .position_y = (16*(vert > 1 ? 0:1)*-1 + 64+8+16 +(i==2 || i==3 ? 6:0)) +			});	 +		} +	} + + +	hh_ppu_update_color(5, 1, (hh_ppu_rgb_color_t) {0xa, 0x3, 0x3}); +	hh_ppu_update_color(5, 2, (hh_ppu_rgb_color_t) {0xc, 0x5, 0x3}); + +	const int _size_havoc = 6; +	int lookup_havoc[6][2]={ +		{0,1},{0,2},//H +		{13,10},{7,8},//av +		{13,11},{13,12}//oc +	}; + +	counter = 8 + (_size_hooded * _size_v); +	for (int i = 0; i < _size_havoc; i++) { +		for (int vert = 1; vert <= _size_v; vert++) { +			//TODO: move 'H' a few pixels to the right for a more cohesive font spacing +			hh_ppu_update_foreground(counter++, (hh_s_ppu_loc_fam_entry) { +				.vertical_flip = false, .horizontal_flip = (i > 4 && vert==0 ? 1:0), +				.palette_index = 5, .tilemap_index = letters_offset + lookup_havoc[i][vert-1], +				.position_x = (16*i +64+32+8), .position_y = (16*(vert > 1 ? 0:1)*-1 + 64+8+48) +			});	 +		} +	} +} diff --git a/src/engine/title_screen.h b/src/engine/title_screen.h new file mode 100644 index 0000000..b5eda63 --- /dev/null +++ b/src/engine/title_screen.h @@ -0,0 +1,3 @@ +#pragma once + +void hh_init_title_screen(); |