Skip to content

Commit

Permalink
some first levels
Browse files Browse the repository at this point in the history
  • Loading branch information
saolsen committed Sep 10, 2015
1 parent df722fe commit 3725f1f
Show file tree
Hide file tree
Showing 7 changed files with 172 additions and 67 deletions.
4 changes: 3 additions & 1 deletion Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,6 @@ the c version, currently only works on osx

[9/08/15] Slowly getting back into this after a long weekend. I think I'm in the middle of debugging the collision detection but I just took a sec to print out better statistics for the performance counter stuff. This is going to be helpful later but I will probably display it as a searchable table in game rather than interact with it as a console log. That way I can corrilate it to other debug info and replay slow frames, etc.

[9/09/15] I was thinking about the game and all the things I want to do for it but what's really important is that it's fun and the puzzles are good. If the puzzles aren't good and the game isn't fun then any other platform / debugger / story / graphics / ui doesn't even matter so I need to refocus on making good levels. I started that by adding an easier way to programattically build levels. I introduced a new data structure to represent a level specification. There are going to be a rich set of functions to build these up. Then when the user loads a level these specs are translated into actuial entities. In that way we make little prefabs (using a unity term) that let me specify a ship is at this location, but when the level is loaded the actual collision geometry and stuff is set up correctly. These are live editable the same way my other code is so I should be able to iterate on level design this way. This will let me really get to work on the core of the game which has to be solid or everything else is a waste of time.
[9/09/15] I was thinking about the game and all the things I want to do for it but what's really important is that it's fun and the puzzles are good. If the puzzles aren't good and the game isn't fun then any other platform / debugger / story / graphics / ui doesn't even matter so I need to refocus on making good levels. I started that by adding an easier way to programattically build levels. I introduced a new data structure to represent a level specification. There are going to be a rich set of functions to build these up. Then when the user loads a level these specs are translated into actuial entities. In that way we make little prefabs (using a unity term) that let me specify a ship is at this location, but when the level is loaded the actual collision geometry and stuff is set up correctly. These are live editable the same way my other code is so I should be able to iterate on level design this way. This will let me really get to work on the core of the game which has to be solid or everything else is a waste of time.

[9/09/15] I'm starting to design puzzles now. I really don't like the design workflow I have. It's very hard to use and to visualize what I want the player to be able to do. It might work for awhile but I think I need to design a level editor. I've been making some progressively challenging levels that try to make the player learn a new way of flying the ship for each level. I don't really know how far something like this can be taken but that's really the mvp I need to create to see if this is even a viable game. I ran into some problems on level 5 though and that collision detection bug is stopping that level from working so I need to take a bit of time and fix that before I can progress.
31 changes: 25 additions & 6 deletions rockets.c
Original file line number Diff line number Diff line change
Expand Up @@ -928,7 +928,7 @@ gui_nodes(GUIState* gui, NodeStore* ns)

void
setup_level(GameState* state) {
load_level(state, 1);
load_level(state, state->current_level);
state->status = RUNNING;
}

Expand All @@ -946,7 +946,7 @@ game_setup(void* game_state, NVGcontext* vg)
"SourceSansPro-Regular.ttf");
// Assert that the font got loaded.
assert(font >= 0);

state->current_level = 1;
setup_level(state);

return state;
Expand All @@ -958,7 +958,7 @@ game_update_and_render(void* gamestate,
NVGcontext* vg,
gg_Input input,
float dt)
{
{
debug_setup_records();
debug_setup_drawing();

Expand Down Expand Up @@ -1005,7 +1005,21 @@ game_update_and_render(void* gamestate,
}

char* reset = "Reset";
if (gui_button_with_text(state->gui, 660, 2.5, 10, 5, reset)) {
if (gui_button_with_text(state->gui, 660, 2.5, 10, 10, reset)) {
setup_level(state);
}

char* previous = "Previous Level";
if (gui_button_with_text(state->gui, 1230, 2.5, 10, 5, previous)) {
state->current_level--;
CLAMP(state->current_level, 0, num_levels);
setup_level(state);
}

char* next = "Next Level";
if (gui_button_with_text(state->gui, 1250, 2.5, 10, 10, next)) {
state->current_level++;
CLAMP(state->current_level, 0, num_levels);
setup_level(state);
}

Expand All @@ -1028,6 +1042,7 @@ game_update_and_render(void* gamestate,
entity->thrusters = new_thrusters;
ship_move(entity, dt);

// this doesn't work anymore because collision detection stop it from getting here.
// @HARDCODE: Fix with collision detection.
// Goal is at (500, 600)
if (bounds_contains(500 - 10,
Expand Down Expand Up @@ -1100,8 +1115,6 @@ game_update_and_render(void* gamestate,
int time_block = BEGIN_TIME_BLOCK();
CollisionRect collision_entity_piece = collision_entity->collision_pieces[cep];


// wudabout the entity_piece.offset

// Check if they collide.
float area_width = collision_entity_piece.width + entity_piece.width;
Expand Down Expand Up @@ -1230,6 +1243,12 @@ game_update_and_render(void* gamestate,
}
nvgRestore(vg);

// Debug draw the mouse location.
nvgBeginPath(vg);
nvgCircle(vg, input.mouse_x, input.mouse_y, 3);
nvgFillColor(vg, nvgRGBf(1,1,1));
nvgFill(vg);

/* debug_print_records(); */
}

Expand Down
62 changes: 8 additions & 54 deletions rockets.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@
* The collision detection stuff isn't working properly.
@TODO: next steps.
* Make a level system where you can pick the level and you can change the level.
* Use collisions for gameplay stuff like hitting the goal to win a level or dying.
* Add boundries to the level.
* Better debug setup. Logging, performance counters, easier debug visualizations.
(watch casey on this stuff today)
* Debug the collision detection code.
* Use collisions for gameplay stuff.
* Make levels.
* Start really making some levels and play with the game mechanics. Any platform work before having
a viable game and levels is just wasted.
Expand Down Expand Up @@ -49,6 +53,8 @@
of debug utils and the drawing stuff abstracted so I can ditch nanovg later.
Real renderer is probably going to be a lot more complex. I want a nice looking game.
For now this vector stuff works fine.
Sort of want my own renderer and then I can implement it for metal or opengl or whatever but
is a ton more work.
Porting
* Once I really have a game it would be great to get it running on a lot of platforms.
Expand All @@ -58,8 +64,6 @@
I'll keep saying and believing this. HMH is the absolute best thing I've ever watched.
Just keep watching it!
*/
#ifndef _game_h
#define _game_h
Expand All @@ -72,58 +76,8 @@
#include "rockets_nodes.h"
#include "rockets_entities.h"
#include "rockets_levels.h"
#include "rockets_gui.h"

// GUI stuff
// @TODO: rockets_gui

typedef struct {
Node* node;
BoundingBox bb;
V2 draw_position;
int input_index;
Node* input_to;
} NodeBounds;

typedef enum { NE_NAH } NodeEventType;

typedef struct {
NodeEventType type;
} NodeEvent;

typedef enum {GUI_NAH,
GUI_DRAGGING_NODE,
GUI_DRAGGING_INPUT,
GUI_DRAGGING_OUTPUT,
GUI_DRAGGING_SLIDER} GUI_State;

typedef enum {DT_NAH,
DT_BODY,
DT_OUTPUT,
DT_INPUT,
DT_SLIDER} DragTarget_Type;

typedef struct {
DragTarget_Type type;
int from_id;
int from_input_num;
V2 from_position; // can calculate from from_id but meh...
V2 position;
int value;
} DragTarget;

typedef struct {
NVGcontext* vg;
gg_Input input;
GUI_State state;
DragTarget drag_target;
} GUIState;

typedef enum { BS_NAH, BS_HOVER, BS_CLICK } ButtonState;

typedef struct entity_pointer_ {
Entity* entity;
struct entity_pointer_* next_entity;
} EntityPointer;

typedef enum {RUNNING, PAUSED, WON, DIED} LevelStatus;

Expand Down
49 changes: 49 additions & 0 deletions rockets_gui.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#ifndef _rockets_gui_h
#define _rockets_gui_h
// GUI stuff
// @TODO: rockets_gui

typedef struct {
Node* node;
BoundingBox bb;
V2 draw_position;
int input_index;
Node* input_to;
} NodeBounds;

typedef enum { NE_NAH } NodeEventType;

typedef struct {
NodeEventType type;
} NodeEvent;

typedef enum {GUI_NAH,
GUI_DRAGGING_NODE,
GUI_DRAGGING_INPUT,
GUI_DRAGGING_OUTPUT,
GUI_DRAGGING_SLIDER} GUI_State;

typedef enum {DT_NAH,
DT_BODY,
DT_OUTPUT,
DT_INPUT,
DT_SLIDER} DragTarget_Type;

typedef struct {
DragTarget_Type type;
int from_id;
int from_input_num;
V2 from_position; // can calculate from from_id but meh...
V2 position;
int value;
} DragTarget;

typedef struct {
NVGcontext* vg;
gg_Input input;
GUI_State state;
DragTarget drag_target;
} GUIState;

typedef enum { BS_NAH, BS_HOVER, BS_CLICK } ButtonState;
#endif
14 changes: 14 additions & 0 deletions rockets_levels.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ void load_level(GameState* state, int level_number)

entity_add_flags(ship, EntityFlag_COLLIDES);

// @NOTE: ship is 40 x 50
CollisionRect* s1 = &ship->collision_pieces[ship->num_collision_pieces++];
s1->offset = v2(-10, -15);
s1->size = v2(20, 40);
Expand All @@ -47,6 +48,19 @@ void load_level(GameState* state, int level_number)
g->offset = v2(-10, -10);
g->size = v2(20, 20);
} break;

case(ES_OBSTICLE): {
Entity* obsticle = push_entity(state);
obsticle->type = EntityType_BOUNDRY;
obsticle->position = entity.position;
obsticle->rotation = 0;

entity_add_flags(obsticle, EntityFlag_COLLIDES);

CollisionRect* o = &obsticle->collision_pieces[obsticle->num_collision_pieces++];
o->offset = v2(-entity.size.x/2, -entity.size.y/2);
o->size = entity.size;
}
}
}
}
75 changes: 71 additions & 4 deletions rockets_levels.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
// These levelspecs are translated into full sets of entities when the level is loaded.
// See rockets_levels.c to see how these are translated into game entities.
typedef enum {ES_PLAYER_SHIP,
ES_GOAL} EntitySpecType;
ES_GOAL,
ES_OBSTICLE} EntitySpecType;

typedef struct {
EntitySpecType type;
int id;
union {
V2 position;
};
V2 position;
V2 size;
} EntitySpec;

typedef struct {
Expand Down Expand Up @@ -47,24 +47,91 @@ add_goal(LevelSpec* level, float x, float y)
return entity->id;
}

int
add_obsticle(LevelSpec* level, float x, float y, float width, float height)
{
EntitySpec* entity = push_entity_spec(level);
entity->type = ES_OBSTICLE;
entity->position = v2(x, y);
entity->size = v2(width, height);
return entity->id;
}


// gotta go up
void level_1(LevelSpec* level)
{
add_player_ship(level, 300, 99);
add_goal(level, 300, 600);
}

// gotta move over
void level_2(LevelSpec* level)
{
add_player_ship(level, 300, 99);
add_goal(level, 500, 600);
}

// gotta move up and over
void level_3(LevelSpec* level)
{
add_player_ship(level, 300, 99);
add_goal(level, 500, 600);
add_obsticle(level, 300, 600, 20, 20);
add_obsticle(level, 500, 99, 20, 20);
}

// gotta move up and over but not at the middle
// @QUESTIONABLE: this one is only a new step if you moved over at exactly the middle, not something
// everyone will hit.
void level_4(LevelSpec* level)
{
add_player_ship(level, 300, 99);
add_goal(level, 500, 600);
add_obsticle(level, 300, 600, 20, 20);
add_obsticle(level, 500, 99, 20, 20);
add_obsticle(level, 400, 350, 20, 20);
}

// gotta turn
void level_5(LevelSpec* level)
{
// ship is 40 x 50 so need a 40px gap you gotta fly through
add_player_ship(level, 100, 99);
add_goal(level, 500, 600);

add_obsticle(level, 300, 165, 40, 330);
add_obsticle(level, 300, 535, 40, 330);

}

// @TODO: Better table here, this is annoying.
LevelSpec get_level_spec(int level)
{
LevelSpec spec = {};
switch(level) {
case(1):
level_1(&spec);
break;
case(2):
level_2(&spec);
break;
case(3):
level_3(&spec);
break;
case(4):
level_4(&spec);
break;
case(5):
level_5(&spec);
break;
default:
log_error("Error, asking for unknown level.");
break;
}
return spec;
}

int num_levels = 1;

#endif
4 changes: 2 additions & 2 deletions rockets_math.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ bounds_contains(float top_leftx, float top_lefty,
float bottom_rightx, float bottom_righty,
float x, float y)
{
return (x > top_leftx && x < bottom_rightx &&
y > top_lefty && y < bottom_righty);
return (x >= top_leftx && x <= bottom_rightx &&
y >= top_lefty && y <= bottom_righty);
}

// Vectors
Expand Down

0 comments on commit 3725f1f

Please sign in to comment.