void GenNextElements() { // Called every game loop, but only does work when close to next challange area if (g_current_race_pos + 2 * G_HEIGHT > g_next_challange_area) { float current_y = g_next_challange_area; LOG(("Current: %f\n", g_next_challange_area)); // Choose how many layers of rocks int nlayers = (int)CORE_URand(1, 20); LOG(("nlayers: %d\n", nlayers)); for (int i = 0; i < nlayers; i++) { LOG(("Where: %f\n", current_y)); // Choose pass point float displace = (current_y - g_last_conditioned.y) * PATH_TWIST_RATIO; float bracket_left = g_last_conditioned.x - displace; float bracket_right = g_last_conditioned.x + displace; bracket_left = MAX(bracket_left, 2.f * MAINSHIP_RADIUS); bracket_right = MIN(bracket_right, G_WIDTH - 2.f * MAINSHIP_RADIUS); g_last_conditioned.y = current_y; g_last_conditioned.x = CORE_FRand(bracket_left, bracket_right); // Choose how many rocks int nrocks = (int)CORE_URand(0, 3); LOG(("nrocks: %d\n", nrocks)); // Generate rocks for (int i = 0; i < nrocks; i++) { // Find a valid position vec2 rockpos; for (;;) { rockpos = vmake(CORE_FRand(0.f, G_WIDTH), current_y); if (rockpos.x + ROCK_RADIUS < g_last_conditioned.x - PATH_WIDTH || rockpos.x - ROCK_RADIUS > g_last_conditioned.x + PATH_WIDTH) break; } // Insert obstacle EType t = E_ROCK; int gfx = g_rock[1/*CORE_URand(0,4)*/]; if (CORE_RandChance(0.1f)) { t = E_MINE; gfx = g_mine; } // Mine? else if (CORE_RandChance(0.1f)) { t = E_DRONE; gfx = g_drone; } // Drone? vec2 vel = vmake(CORE_FRand(-0.5f, 0.5f), CORE_FRand(-0.5f, 0.5f)); // velocity InsertEntity(t, rockpos, vel, ROCK_RADIUS, gfx, true); // Insert the chosen entity } current_y += CORE_FRand(300.f, 600.f); } g_next_challange_area = current_y + CORE_FRand(.5f * G_HEIGHT, 1.5f * G_HEIGHT); } }
//---------------------------------------------------------------------------- void ResetNewGame() { // Reset everything for a new game g_next_challange_area = FIRST_CHALLANGE; g_last_conditioned = vmake(0.5f * G_WIDTH, 0.f); g_current_race_pos = 0.f; g_camera_offset = 0.f; g_rock_chance = START_ROCK_CHANCE_PER_PIXEL; g_gs = GS_STARTING; g_gs_timer = 0.f; // Start logic for (int i = 0; i < MAX_ENTITIES; i++) { g_entities[i].type = E_NULL; } // Insert main ship InsertEntity(E_MAIN, vmake(G_WIDTH / 2.0, G_HEIGHT / 8.f), vmake(0.f, SHIP_START_SPEED), MAINSHIP_RADIUS, g_ship_C, true); }
void initCursor() { cursor = new tCursor; if( cursor) { cursor->pos= vmake(SCR_WIDTH*.7f, SCR_HEIGHT*.7f); cursor->radius=100.0; cursor->index = texcursor; } }
bool initEmmiter() { myEmmiter = new tEmitter; strcpy(myEmmiter->name,"emmiter1"); myEmmiter->id=0x0001; myEmmiter->flags=0; myEmmiter->prev=0;myEmmiter->next=0; myEmmiter->pos = vmake(SCR_WIDTH*.5f, SCR_HEIGHT*.3f); myEmmiter->vel = vmake(10.0,10.0); myEmmiter->speedVar = 10.0f; myEmmiter->particle=0; myEmmiter->maxParticles= MAX_PARTICLES; myEmmiter->particleCount=0; myEmmiter->emitsPerFrame = 1;//NUM_PARTICLES/10; myEmmiter->emitVar = 10;//NUM_PARTICLES/10; myEmmiter->life = 1000; myEmmiter->lifeVar = 50; myEmmiter->forces = vmake(0.0,0.0); return true; }
void renderParticles(tEmitter *emitter) { if (emitter->particle != NULL) { tParticle* particle = emitter->particle; while (particle) { CORE_RenderCenteredSprite(particle->pos, vmake(particle->radius , particle->radius ), particle->index); particle = particle->next; } } }
//----------------------------------------------------------------------------- void InsertEntity(EType type, vec2 pos, vec2 vel, float radius, int gfx, bool has_shadow, bool additive = false) { for (int i = 0; i < MAX_ENTITIES; i++) { if (g_entities[i].type == E_NULL) { g_entities[i].type = type; g_entities[i].pos = pos; g_entities[i].vel = vel; g_entities[i].radius = radius; g_entities[i].gfx = gfx; g_entities[i].energy = MAX_ENERGY; g_entities[i].fuel = MAX_FUEL; g_entities[i].tilt = 0.f; g_entities[i].gfxscale = 1.f; g_entities[i].gfxadditive = additive; g_entities[i].color = vmake(1.f, 1.f, 1.f, 1.f); g_entities[i].has_shadow = has_shadow; break; } } }
int Main(void) { // Load resources texsmallball = CORE_LoadBmp("data/tyrian_ball.32.bmp" , false); texcursor = CORE_LoadBmp("data/cursor.bmp", false); initCursor(); initParticlePool(MAX_PARTICLES); initEmmiter(); // Set up rendering glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT); // Sets up clipping glClearColor( 0.0f, 0.1f, 0.3f, 0.0f ); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho( 0.0, SCR_WIDTH, 0.0, SCR_HEIGHT, 0.0, 1.0); glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); DWORD start_tick= GetTickCount(); while (!SYS_GottaQuit()) { // Render glClear( GL_COLOR_BUFFER_BIT ); CORE_RenderCenteredSprite(cursor->pos, vmake(cursor->radius , cursor->radius ), cursor->index); //fixed substep float dt =1.0f/(substep*FPS); //add gravity // tVector emitterforces=vmake(0.0f,0.0f); tVector emitterforces= GRAVITY; //vmake(0,gravityForce); updateEmitter( myEmmiter, emitterforces, dt); applyDeflectors(myEmmiter); renderParticles(myEmmiter); SYS_Show(); start_tick= GetTickCount(); // Keypress! const float scale=2.0f; if (SYS_KeyPressed('O')) { if(cursor)cursor->pos.x-=1.0f*scale; } if (SYS_KeyPressed('P')) { if(cursor)cursor->pos.x+=1.0f*scale; } if (SYS_KeyPressed('Q')) { if(cursor)cursor->pos.y+=1.0f*scale; } if (SYS_KeyPressed('A')) { if(cursor)cursor->pos.y-=1.0f*scale; } if (SYS_KeyPressed('S')) { atractorScale*=1.1f; if( atractorScale > 1000.0f)atractorScale=1000.0f; } if (SYS_KeyPressed('W')) { atractorScale*=0.9f; } // Keep system running SYS_Pump(); SYS_Sleep(17); } CORE_UnloadBmp(texsmallball); CORE_UnloadBmp(texcursor); destroyEmmmiter(myEmmiter); destroyParticlePool(); destroyCursor(); return 0; }
static void cpArbiterApplyImpulse_NEON(cpArbiter *arb) { cpBody *a = arb->body_a; cpBody *b = arb->body_b; cpFloatx2_t surface_vr = vld((cpFloat_t *)&arb->surface_vr); cpFloatx2_t n = vld((cpFloat_t *)&arb->n); cpFloat_t friction = arb->u; int numContacts = arb->count; struct cpContact *contacts = arb->contacts; for(int i=0; i<numContacts; i++) { struct cpContact *con = contacts + i; cpFloatx2_t r1 = vld((cpFloat_t *)&con->r1); cpFloatx2_t r2 = vld((cpFloat_t *)&con->r2); cpFloatx2_t perp = vmake(-1.0, 1.0); cpFloatx2_t r1p = vmul(vrev(r1), perp); cpFloatx2_t r2p = vmul(vrev(r2), perp); cpFloatx2_t vBias_a = vld((cpFloat_t *)&a->v_bias); cpFloatx2_t vBias_b = vld((cpFloat_t *)&b->v_bias); cpFloatx2_t wBias = vmake(a->w_bias, b->w_bias); cpFloatx2_t vb1 = vadd(vBias_a, vmul_n(r1p, vget_lane(wBias, 0))); cpFloatx2_t vb2 = vadd(vBias_b, vmul_n(r2p, vget_lane(wBias, 1))); cpFloatx2_t vbr = vsub(vb2, vb1); cpFloatx2_t v_a = vld((cpFloat_t *)&a->v); cpFloatx2_t v_b = vld((cpFloat_t *)&b->v); cpFloatx2_t w = vmake(a->w, b->w); cpFloatx2_t v1 = vadd(v_a, vmul_n(r1p, vget_lane(w, 0))); cpFloatx2_t v2 = vadd(v_b, vmul_n(r2p, vget_lane(w, 1))); cpFloatx2_t vr = vsub(v2, v1); cpFloatx2_t vbn_vrn = vpadd(vmul(vbr, n), vmul(vr, n)); cpFloatx2_t v_offset = vmake(con->bias, -con->bounce); cpFloatx2_t jOld = vmake(con->jBias, con->jnAcc); cpFloatx2_t jbn_jn = vmul_n(vsub(v_offset, vbn_vrn), con->nMass); jbn_jn = vmax(vadd(jOld, jbn_jn), vdup_n(0.0)); cpFloatx2_t jApply = vsub(jbn_jn, jOld); cpFloatx2_t t = vmul(vrev(n), perp); cpFloatx2_t vrt_tmp = vmul(vadd(vr, surface_vr), t); cpFloatx2_t vrt = vpadd(vrt_tmp, vrt_tmp); cpFloatx2_t jtOld = {}; jtOld = vset_lane(con->jtAcc, jtOld, 0); cpFloatx2_t jtMax = vrev(vmul_n(jbn_jn, friction)); cpFloatx2_t jt = vmul_n(vrt, -con->tMass); jt = vmax(vneg(jtMax), vmin(vadd(jtOld, jt), jtMax)); cpFloatx2_t jtApply = vsub(jt, jtOld); cpFloatx2_t i_inv = vmake(-a->i_inv, b->i_inv); cpFloatx2_t nperp = vmake(1.0, -1.0); cpFloatx2_t jBias = vmul_n(n, vget_lane(jApply, 0)); cpFloatx2_t jBiasCross = vmul(vrev(jBias), nperp); cpFloatx2_t biasCrosses = vpadd(vmul(r1, jBiasCross), vmul(r2, jBiasCross)); wBias = vadd(wBias, vmul(i_inv, biasCrosses)); vBias_a = vsub(vBias_a, vmul_n(jBias, a->m_inv)); vBias_b = vadd(vBias_b, vmul_n(jBias, b->m_inv)); cpFloatx2_t j = vadd(vmul_n(n, vget_lane(jApply, 1)), vmul_n(t, vget_lane(jtApply, 0))); cpFloatx2_t jCross = vmul(vrev(j), nperp); cpFloatx2_t crosses = vpadd(vmul(r1, jCross), vmul(r2, jCross)); w = vadd(w, vmul(i_inv, crosses)); v_a = vsub(v_a, vmul_n(j, a->m_inv)); v_b = vadd(v_b, vmul_n(j, b->m_inv)); // TODO would moving these earlier help pipeline them better? vst((cpFloat_t *)&a->v_bias, vBias_a); vst((cpFloat_t *)&b->v_bias, vBias_b); vst_lane((cpFloat_t *)&a->w_bias, wBias, 0); vst_lane((cpFloat_t *)&b->w_bias, wBias, 1); vst((cpFloat_t *)&a->v, v_a); vst((cpFloat_t *)&b->v, v_b); vst_lane((cpFloat_t *)&a->w, w, 0); vst_lane((cpFloat_t *)&b->w, w, 1); vst_lane((cpFloat_t *)&con->jBias, jbn_jn, 0); vst_lane((cpFloat_t *)&con->jnAcc, jbn_jn, 1); vst_lane((cpFloat_t *)&con->jtAcc, jt, 0); } }
int Main(void) { // Load resources texsmallball = CORE_LoadBmp("data/tyrian_ball.32.bmp" , false); texcursor = CORE_LoadBmp("data/cursor.bmp", false); initCursor(); initParticlePool(MAX_PARTICLES); //checking pool //while(particlePool.current) //{ // particlePool.current=particlePool.current->next; //} //particlePool.current = particlePool.head->next; initEmmiter(); //for (int i = 0; i < NUM_PARTICLES; i++) //{ //float radius; //radius = 8.f; //particle[i]=particlePool.current; //particlePool.current=particlePool.current->next; //particle[i]->radius = radius; //particle[i]->mass = 1.f; //particle[i]->index = texsmallball; //particle[i]->pos = vmake(CORE_FRand(radius, SCR_WIDTH-radius), CORE_FRand(radius, SCR_HEIGHT-radius)); //particle[i]->vel = vmake(CORE_FRand(-MAX_BALL_SPEED, +MAX_BALL_SPEED), CORE_FRand(-MAX_BALL_SPEED, +MAX_BALL_SPEED)); //} // Set up rendering glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT); // Sets up clipping glClearColor( 0.0f, 0.1f, 0.3f, 0.0f ); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho( 0.0, SCR_WIDTH, 0.0, SCR_HEIGHT, 0.0, 1.0); glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); DWORD start_tick= GetTickCount(); while (!SYS_GottaQuit()) { // Render glClear( GL_COLOR_BUFFER_BIT ); CORE_RenderCenteredSprite(cursor->pos, vmake(cursor->radius , cursor->radius ), cursor->index); //fixed substep float dt =1.0f/(substep*FPS); //adaptive substep //DWORD elapsed_ticks= GetTickCount()- start_tick; //float elapsed_dt= elapsed_ticks/TICKS_PER_SECOND; //float edt_dt = elapsed_dt/dt; //int ite = (int)edt_dt; //float lastdt= edt_dt - ite; tVector forces=vmake(0,-100.0f); // for( int i=0; i < ite; i++) updateEmitter( myEmmiter, forces, dt); // updateEmitter( myEmmiter, forces, lastdt); applyDeflectors(myEmmiter); renderParticles(myEmmiter); SYS_Show(); start_tick= GetTickCount(); // Keypress! if (SYS_KeyPressed('O')) { if(cursor)cursor->pos.x-=1.0f;; } if (SYS_KeyPressed('P')) { if(cursor)cursor->pos.x+=1.0f;; } if (SYS_KeyPressed('Q')) { if(cursor)cursor->pos.y+=1.0f;; } if (SYS_KeyPressed('A')) { if(cursor)cursor->pos.y-=1.0f;; } if (0)//SYS_KeyPressed('I')) { //start single ball at random float radius=16.f; GLuint texBall=texsmallball; float mass=1.0f; int index=(int)CORE_FRand(0, MAX_PARTICLES-1); //particle[index]->mass = mass; //particle[index]->index = texBall; //particle[index]->radius = radius; // particle[index]->pos = vmake(CORE_FRand(radius, SCR_WIDTH-radius), CORE_FRand(SCR_HEIGHT*.5f, SCR_HEIGHT-radius)); //particle[index]->vel = vmake(0, 10); } if (0)//SYS_KeyPressed(' ')) { //give an impulse to all balss // for (int i = 0; i < MAX_PARTICLES; i++) // { //if (fabs(particle[i]->vel.x) < 0.1f) // particle[i]->vel.x = CORE_FRand(-MAX_BALL_SPEED, +MAX_BALL_SPEED); //particle[i]->vel.y = CORE_FRand(0, JUMP_SPEED); // } } if (0)//SYS_KeyPressed(VK_CONTROL)) { //reset all glClear( GL_COLOR_BUFFER_BIT ); // for (int i = 0; i < MAX_PARTICLES; i++) // { //float radius=particle[i]->radius; //particle[i]->pos = vmake(CORE_FRand(radius, SCR_WIDTH-radius), CORE_FRand(radius, SCR_HEIGHT-radius)); //particle[i]->vel = vmake(0, 10); // } SYS_Show(); } // Keep system running SYS_Pump(); SYS_Sleep(17); } CORE_UnloadBmp(texsmallball); CORE_UnloadBmp(texcursor); destroyEmmmiter(myEmmiter); destroyParticlePool(); destroyCursor(); return 0; }
//----------------------------------------------------------------------------- void RunGame() { // Control main ship if (g_gs == GS_VICTORY || g_gs == GS_STARTING) { if (MAIN_SHIP.vel.y < SHIP_CRUISE_SPEED) { MAIN_SHIP.vel.y = SAFEADD(MAIN_SHIP.vel.y, SHIP_INC_SPEED, SHIP_CRUISE_SPEED); } MAIN_SHIP.fuel = SAFESUB(MAIN_SHIP.fuel, FRAME_FUEL_COST); } // Heal main ship if (g_gs != GS_DYING) { if (MAIN_SHIP.energy < MAX_ENERGY && MAIN_SHIP.fuel > MIN_FUEL_FOR_HEAL) { MAIN_SHIP.energy = SAFEADD(MAIN_SHIP.energy, ENERGY_HEAL_PER_FRAME, MAX_ENERGY); MAIN_SHIP.fuel = SAFESUB(MAIN_SHIP.fuel, FUEL_HEAL_PER_FRAME); LOG(("- energy: %f, fuel: %f\n", MAIN_SHIP.energy, MAIN_SHIP.fuel)); } } // Move entities for (int i = MAX_ENTITIES - 1; i >= 0; i--) { if (g_entities[i].type != E_NULL) { g_entities[i].pos = vadd(g_entities[i].pos, g_entities[i].vel); // Remove entities that fell off screen if (g_entities[i].pos.y < g_camera_offset - G_HEIGHT) g_entities[i].type = E_NULL; } } // Advance "stars" for (int i = 0; i < MAX_ENTITIES; i++) { if (g_entities[i].type == E_STAR) g_entities[i].gfxscale *= 1.008f; } // Dont let steering off the screen if (MAIN_SHIP.pos.x < MAINSHIP_RADIUS) MAIN_SHIP.pos.x = MAINSHIP_RADIUS; if (MAIN_SHIP.pos.x > G_WIDTH - MAINSHIP_RADIUS) MAIN_SHIP.pos.x = G_WIDTH - MAINSHIP_RADIUS; // Check collisions if (g_gs == GS_PLAYING) { // Check everything against ship for (int i = 1; i < MAX_ENTITIES; i++) { // Should check against ship? if (g_entities[i].type == E_ROCK || g_entities[i].type == E_JUICE || g_entities[i].type == E_MINE || g_entities[i].type == E_DRONE) { float distance = vlen2(vsub(g_entities[i].pos, MAIN_SHIP.pos)); // Distance from object to ship float crash_distance = CORE_FSquare(g_entities[i].radius + MAIN_SHIP.radius); // Minimum allowed distance before crash if (distance < crash_distance) { switch (g_entities[i].type) { case E_ROCK: if (g_entities[i].energy > 0) { MAIN_SHIP.energy = SAFESUB(MAIN_SHIP.energy, ROCK_CRASH_ENERGY_LOSS); MAIN_SHIP.vel.y = SHIP_START_SPEED; // Set rock velocity vec2 vel_direction = vsub(g_entities[i].pos, MAIN_SHIP.pos); // direction of rock velocity, away from ship vec2 normalized_vel_direction = vunit(vel_direction); // normalize vec2 vel = vscale(normalized_vel_direction, CRASH_VEL); // Scale, ie give the rock correct speed. g_entities[i].vel = vel; g_entities[i].energy = 0; } break; case E_JUICE: MAIN_SHIP.fuel = SAFEADD(MAIN_SHIP.fuel, JUICE_FUEL, MAX_FUEL); g_entities[i].type = E_NULL; break; case E_MINE: MAIN_SHIP.energy = SAFESUB(MAIN_SHIP.energy, MINE_CRASH_ENERGY_LOSS); MAIN_SHIP.vel.y = SHIP_START_SPEED; g_entities[i].type = E_NULL; break; case E_DRONE: MAIN_SHIP.energy = SAFESUB(MAIN_SHIP.energy, MINE_CRASH_ENERGY_LOSS); MAIN_SHIP.vel.y = SHIP_START_SPEED; g_entities[i].type = E_NULL; break; default: break; } } } else if (g_entities[i].type == E_ROCKET) { // Check all hit-able objects against this rocket for (int j = 1; i < MAX_ENTITIES; j++) { // Should check against rocket? if (g_entities[j].type == E_ROCK || g_entities[j].type == E_MINE || g_entities[j].type == E_DRONE) { float distance = vlen2(vsub(g_entities[i].pos, g_entities[j].pos)); float crash_distance = CORE_FSquare(g_entities[i].radius + g_entities[j].radius); if (distance < crash_distance) { // Impact! g_entities[i].type = E_NULL; g_entities[j].type = E_NULL; break; } } } } } } // Generate new level elements as we advance GenNextElements(); // Possibly insert new juice if (g_gs == GS_PLAYING) { float trench = MAIN_SHIP.pos.y - g_current_race_pos; // How much advanced from previous frame if (CORE_RandChance(trench * JUICE_CHANCE_PER_PIXEL)) { vec2 pos = vmake(CORE_FRand(0.f, G_WIDTH), g_camera_offset + G_HEIGHT + GEN_IN_ADVANCE); // Random x, insert 400y above window vec2 vel = vmake(CORE_FRand(-1.f, +1.f), CORE_FRand(-1.f, +1.f)); // Random small velocity to make rocks "float" InsertEntity(E_JUICE, pos, vel, JUICE_RADIUS, g_juice, false, true); } } // Set camera to follow the main ship g_camera_offset = MAIN_SHIP.pos.y - G_HEIGHT / 8.f; g_current_race_pos = MAIN_SHIP.pos.y; if (g_gs == GS_PLAYING) { if (g_current_race_pos >= RACE_END) // Check if victory { g_gs = GS_VICTORY; g_gs_timer = 0.f; MAIN_SHIP.gfxadditive = true; } } // Advance game mode g_gs_timer += FRAMETIME; switch (g_gs) { case GS_STARTING: if (g_gs_timer >= STARTING_TIME) // Start delay before starting to play { g_gs = GS_PLAYING; g_gs_timer = 0.f; } break; case GS_DYING: if (g_gs_timer >= DYING_TIME) { ResetNewGame(); } break; case GS_PLAYING: if (MAIN_SHIP.energy <= 0.f || MAIN_SHIP.fuel <= 0.f) // No energy or fuel --> die { g_gs = GS_DYING; g_gs_timer = 0.f; MAIN_SHIP.gfx = g_ship_RR; } break; case GS_VICTORY: if (CORE_RandChance(1.f / 10.f)) { InsertEntity(E_STAR, MAIN_SHIP.pos, vadd(MAIN_SHIP.vel, vmake(CORE_FRand(-5.f, 5.f), CORE_FRand(-5.f, 5.f))), 0, g_star, false, true); } if (g_gs_timer >= 8.f) // Should use VICTORY_TIME, but stupid VS dont want me to... { ResetNewGame(); } break; } g_time_from_last_rocket += FRAMETIME; }
void Render() { glClear(GL_COLOR_BUFFER_BIT); // Render background, only tiles within camera view int first_tile = (int)floorf(g_camera_offset / G_HEIGHT); for (int i = first_tile; i < first_tile + 2; i++) { vec2 pos = vsub(vadd(vmake(G_WIDTH / 2.0f, G_HEIGHT / 2.0f), vmake(0.f, (float)i * G_HEIGHT)), vmake(0.f, g_camera_offset)); // split up, what does it? vec2 size = vmake(G_WIDTH, G_HEIGHT); CORE_RenderCenteredSprite(pos, size, g_bkg); } // Draw entities for (int i = MAX_ENTITIES - 1; i >= 0; i--) { if (g_entities[i].type != E_NULL) { ivec2 size = CORE_GetBmpSize(g_entities[i].gfx); vec2 pos = g_entities[i].pos; pos.x = (float)((int)pos.x); pos.y = (float)((int)pos.y); if (g_entities[i].has_shadow) // renders shadows first { vec2 s_pos = vadd(vsub(pos, vmake(0.f, g_camera_offset)), vmake(0.f, -SHADOW_OFFSET)); vec2 s_size = vmake(size.x * SPRITE_SCALE * g_entities[i].gfxscale * SHADOW_SCALE, size.y * SPRITE_SCALE * g_entities[i].gfxscale * SHADOW_SCALE); int s_texture = g_entities[i].gfx; rgba s_color = vmake(0.f, 0.f, 0.f, 0.4f); bool s_additive = g_entities[i].gfxadditive; CORE_RenderCenteredSprite(s_pos, s_size, s_texture, s_color, s_additive); } // Render not shadows vec2 offset_pos = vsub(pos, vmake(0.f, g_camera_offset)); // Adjust to where camera is at vec2 scaled_size = vmake(size.x * SPRITE_SCALE * g_entities[i].gfxscale, size.y * SPRITE_SCALE * g_entities[i].gfxscale); int texture = g_entities[i].gfx; rgba color = g_entities[i].color; bool additive = g_entities[i].gfxadditive; CORE_RenderCenteredSprite(offset_pos, scaled_size, texture, color, additive); } } if (g_gs != GS_VICTORY) // if not yet won { // Draw UI // The energy bar float energy_ratio = MAIN_SHIP.energy / MAX_ENERGY; vec2 e_bar_pos = vmake(ENERGY_BAR_W / 2.f, energy_ratio * ENERGY_BAR_H / 2.f); vec2 e_bar_size = vmake(ENERGY_BAR_W, ENERGY_BAR_H * energy_ratio); CORE_RenderCenteredSprite(e_bar_pos, e_bar_size, g_energy, COLOR_WHITE, true); // The fuel bar float fuel_ratio = MAIN_SHIP.fuel / MAX_FUEL; vec2 f_bar_pos = vmake(G_WIDTH - FUEL_BAR_W / 2.f, fuel_ratio * FUEL_BAR_H / 2.f); vec2 f_bar_size = vmake(FUEL_BAR_W, FUEL_BAR_H * fuel_ratio); CORE_RenderCenteredSprite(f_bar_pos, f_bar_size, g_fuel, COLOR_WHITE, true); // Draw how long you have lasted int num_chunks = (int)((g_current_race_pos / RACE_END) * MAX_CHUNKS); for (int i = 0; i < num_chunks; i++) { vec2 c_pos = vmake(G_WIDTH - 100.f, 50.f + i * 50.f); vec2 c_size = vmake(CHUNK_W, CHUNK_H); CORE_RenderCenteredSprite(c_pos, c_size, g_pearl); } } }
CORE_UnloadBmp(g_bkg); CORE_UnloadBmp(g_rock[0]); CORE_UnloadBmp(g_rock[1]); CORE_UnloadBmp(g_rock[2]); CORE_UnloadBmp(g_rock[3]); CORE_UnloadBmp(g_rock[4]); CORE_UnloadBmp(g_pearl); CORE_UnloadBmp(g_energy); CORE_UnloadBmp(g_fuel); CORE_UnloadBmp(g_star); } //---------------------------------------------------------------------------------- // Level generation float g_next_challange_area = FIRST_CHALLANGE; vec2 g_last_conditioned = vmake(0.f, 0.f); #define PATH_TWIST_RATIO .5f // This means about 30 degrees maximum #define PATH_WIDTH (2.f * MAINSHIP_RADIUS) void GenNextElements() { // Called every game loop, but only does work when close to next challange area if (g_current_race_pos + 2 * G_HEIGHT > g_next_challange_area) { float current_y = g_next_challange_area; LOG(("Current: %f\n", g_next_challange_area)); // Choose how many layers of rocks int nlayers = (int)CORE_URand(1, 20); LOG(("nlayers: %d\n", nlayers)); for (int i = 0; i < nlayers; i++)