void SideScroller::collisionY(Entity *entity) { int tileX; int tileY; worldToTileCoordinates(entity->x, entity->y - entity->height*0.5, &tileX, &tileY); if (isSolid(levelData[tileY][tileX])) { entity->y = -2.5f; entity->collidedBottom = true; } }
float GameApp::checkPointForGridCollisionsX(float x, float y) { int gridX, gridY; worldToTileCoordinates(x, y, &gridX, &gridY); if (gridX < 0 || gridX > 128 || gridY < 0 || gridY > 40) return 0.0f; if (isSolid(levelData[gridY][gridX])) { float xCoord = (gridX * TILE_SIZE) - (TILE_SIZE*0.0f); return x - xCoord; } return 0.0; }
// simple collision checks // if colliding, move player to diff location, in this case, right next to the tile void SideScroller::collisionX(Entity *entity) { int tileX; int tileY; // left worldToTileCoordinates(entity->x - entity->width*0.5, entity->y, &tileX, &tileY); if (isSolid(levelData[tileY][tileX])) { entity->x = -6.3f; entity->collidedLeft = true; } else { entity->collidedLeft = false; } // right worldToTileCoordinates(entity->x + entity->width*0.5, entity->y, &tileX, &tileY); if (isSolid(levelData[tileY][tileX])) { entity->x = 9.1f; entity->collidedRight = true; } else { entity->collidedRight = false; } }
void ClassDemoApp::Update(float elapsed) { const Uint8 *keys = SDL_GetKeyboardState(NULL); //Player commands if (keys[SDL_SCANCODE_UP] && player->collidedBottom) { player->velocity_y = 5.8f; player->collidedBottom = false; } if (keys[SDL_SCANCODE_LEFT]) { player->acceleration_x = -5.8f; } else if (keys[SDL_SCANCODE_RIGHT]) { player->acceleration_x = 5.8f; } else { player->acceleration_x = 0; } //Global entities update for (size_t i = 0; i < entities.size(); i++) if (!entities[i]->isStatic) { //Update acceleration and velocities of entities entities[i]->Update(elapsed); int gridX = 0, gridY = 0; //Perform Y calculations and collision with world map entities[i]->y += entities[i]->velocity_y * elapsed; worldToTileCoordinates(entities[i]->x, entities[i]->y - entities[i]->height / 2, gridX, gridY); if (gridX >= 0 && gridY <= 0 && levelData[-gridY][gridX] == 13) { entities[i]->y = gridY * TILE_SIZE + entities[i]->height / 2 + 0.000001f; entities[i]->velocity_y = 0; entities[i]->collidedBottom = true; baseTouchX = gridX; } worldToTileCoordinates(entities[i]->x, entities[i]->y + entities[i]->height / 2, gridX, gridY); if (gridX >= 0 && gridY <= 0 && levelData[-gridY][gridX] == 13) { entities[i]->y = (gridY - 1) * TILE_SIZE - entities[i]->height / 2 - 0.000001f; entities[i]->velocity_y = 0; entities[i]->collidedTop = true; } //Perform X calculations and collision with world map entities[i]->x += entities[i]->velocity_x * elapsed; worldToTileCoordinates(entities[i]->x - entities[i]->width / 2, entities[i]->y, gridX, gridY); if (gridX >= 0 && gridY <= 0 && levelData[-gridY][gridX] == 13) { entities[i]->x = (gridX + 1) * TILE_SIZE + entities[i]->width / 2 + 0.000001f; entities[i]->velocity_x = 0; entities[i]->collidedLeft = true; } worldToTileCoordinates(entities[i]->x + entities[i]->width / 2, entities[i]->y, gridX, gridY); if (gridX >= 0 && gridY <= 0 && levelData[-gridY][gridX] == 13) { entities[i]->x = gridX * TILE_SIZE - entities[i]->width / 2 - 0.000001f; entities[i]->velocity_x = 0; entities[i]->collidedRight = true; } if (entities[i]->y < TILE_SIZE * -LEVEL_HEIGHT) { entities[i]->y = TILE_SIZE * -2; entities[i]->x = TILE_SIZE * baseTouchX + entities[i]->width / 2; entities[i]->velocity_y = 0; } } }
void ClassDemoApp::Update(float elapsed) { const Uint8 *keys = SDL_GetKeyboardState(NULL); for (int i = 0; i < 2; i++) { //Player control if (keys[controls[i]->EXTEND]) { if (keys[controls[i]->UP]) { if (!players[i]->collidedTop) { float oldHeight = players[i]->height; players[i]->height = lerp(players[i]->height, 5 * BOX_SIZE, 0.03f); players[i]->y += (players[i]->height - oldHeight) / 2; } float oldWidth = players[i]->width; players[i]->width = lerp(players[i]->width, BOX_SIZE, 0.06f); players[i]->x += players[i]->lastDirectionX * (players[i]->width - oldWidth) / 2; } else if (keys[controls[i]->DOWN]) { if (!players[i]->collidedBottom) { float oldHeight = players[i]->height; players[i]->height = lerp(players[i]->height, 5 * BOX_SIZE, 0.03f); players[i]->y -= (players[i]->height - oldHeight) / 2; } float oldWidth = players[i]->width; players[i]->width = lerp(players[i]->width, BOX_SIZE, 0.06f); players[i]->x += players[i]->lastDirectionX * (players[i]->width - oldWidth) / 2; } else if (keys[controls[i]->LEFT]) { if (!players[i]->collidedLeft) { float oldWidth = players[i]->width; players[i]->width = lerp(players[i]->width, 5 * BOX_SIZE, 0.02f); players[i]->x -= (players[i]->width - oldWidth) / 2; players[i]->lastDirectionX = 1; } float oldHeight = players[i]->height; players[i]->height = lerp(players[i]->height, BOX_SIZE, 0.04f); players[i]->y += (oldHeight - players[i]->height) / 2; players[i]->velocity_y += (oldHeight - players[i]->height) * 3.4f; } else if (keys[controls[i]->RIGHT]) { if (!players[i]->collidedRight) { float oldWidth = players[i]->width; players[i]->width = lerp(players[i]->width, 5 * BOX_SIZE, 0.02f); players[i]->x += (players[i]->width - oldWidth) / 2; players[i]->lastDirectionX = -1; } float oldHeight = players[i]->height; players[i]->height = lerp(players[i]->height, BOX_SIZE, 0.04f); players[i]->y += (oldHeight - players[i]->height) / 2; players[i]->velocity_y += (oldHeight - players[i]->height) * 3.4f; } else { float oldWidth = players[i]->width; players[i]->width = lerp(players[i]->width, BOX_SIZE, 0.003f); players[i]->x += players[i]->lastDirectionX * (players[i]->width - oldWidth) / 2; float oldHeight = players[i]->height; players[i]->height = lerp(players[i]->height, BOX_SIZE, 0.006f); players[i]->y += (oldHeight - players[i]->height) / 2; players[i]->velocity_y += (oldHeight - players[i]->height) * 3.4f; } players[i]->acceleration_x = 0; } else { if (keys[controls[i]->UP]) { float oldHeight = players[i]->height; players[i]->height = lerp(players[i]->height, BOX_SIZE, 0.08f); players[i]->y += (oldHeight - players[i]->height) / 2; players[i]->velocity_y += (oldHeight - players[i]->height) * 3.6f; } else if (keys[controls[i]->DOWN]) { float oldHeight = players[i]->height; players[i]->height = lerp(players[i]->height, BOX_SIZE, 0.06f); players[i]->y -= (oldHeight - players[i]->height) / 2; } else { float oldHeight = players[i]->height; players[i]->height = lerp(players[i]->height, BOX_SIZE, 0.04f); players[i]->y += (oldHeight - players[i]->height) / 2; players[i]->velocity_y += (oldHeight - players[i]->height); } if (keys[controls[i]->LEFT]) { players[i]->acceleration_x = -0.2f; float oldWidth = players[i]->width; players[i]->width = lerp(players[i]->width, BOX_SIZE, 0.09f); players[i]->x -= (oldWidth - players[i]->width) / 2; players[i]->velocity_x -= (oldWidth - players[i]->width) * 1.4f; } else if (keys[controls[i]->RIGHT]) { players[i]->acceleration_x = 0.2f; float oldWidth = players[i]->width; players[i]->width = lerp(players[i]->width, BOX_SIZE, 0.09f); players[i]->x += (oldWidth - players[i]->width) / 2; players[i]->velocity_x += (oldWidth - players[i]->width) * 1.4f; } else { float oldWidth = players[i]->width; players[i]->width = lerp(players[i]->width, BOX_SIZE, 0.04f); players[i]->x += players[i]->lastDirectionX * (players[i]->width - oldWidth) / 2; players[i]->acceleration_x = 0; } } } flag1 = false; flag2 = false; flag3 = false; //Global entities update for (size_t i = 0; i < entities.size(); i++) { if (!entities[i]->isStatic) { //Update acceleration and velocities of entities entities[i]->Update(elapsed); int gridX = 0, gridY = 0; worldToTileCoordinates(entities[i]->x, entities[i]->y, gridX, gridY); if (gridX == 5 && gridY == -6) { flag1 = true; } if ((gridX == 9 || gridX == 10) && (gridY == -6 || gridY == -7)) { flag2 = true; } if (gridX == 16 && gridY == -7) { flag3 = true; } if ((gridX == 14 || gridX == 15) && (gridY == -23 || gridY == -24)) { ResetPos(); } for (size_t j = 0; j < entities.size(); j++) { if (j != i && entities[i]->CollidesWith(entities[j])) { if (entities[i]->entityType == Entity::ENTITY_PLAYER) { float xDiff = entities[i]->x - entities[j]->x; float yDiff = entities[i]->y - entities[j]->y; float topPen = (entities[j]->y + entities[j]->height / 2) - (entities[i]->y - entities[i]->height / 2); float bottomPen = (entities[i]->y + entities[i]->height / 2) - (entities[j]->y - entities[j]->height / 2); float leftPen = (entities[j]->x + entities[j]->width / 2) - (entities[i]->x - entities[i]->width / 2); float rightPen = (entities[i]->x + entities[i]->width / 2) - (entities[j]->x - entities[j]->width / 2); if (std::max(leftPen, rightPen) / (entities[i]->width + entities[j]->width) > std::max(topPen, bottomPen) / (entities[i]->height + entities[j]->height)) { //Horizontial collision : this condition indicates that entityI is to a side of entityJ entities[i]->velocity_x = (entities[i]->velocity_x + entities[j]->velocity_x) / 2; entities[j]->velocity_x = entities[i]->velocity_x; bool collisionLR = entities[i]->entityType == Entity::ENTITY_PLAYER && ((entities[i] == players[0] && keys[controls[0]->EXTEND] && (keys[controls[0]->LEFT] || keys[controls[0]->RIGHT])) || (entities[i] == players[1] && keys[controls[1]->EXTEND] && (keys[controls[1]->LEFT] || keys[controls[1]->RIGHT]))); if (xDiff > 0) { //J <- I if (!entities[j]->collidedLeft && collisionLR) { entities[j]->x = entities[i]->x - entities[i]->width / 2 - entities[j]->width / 2; } else { entities[i]->x = entities[j]->x + entities[j]->width / 2 + entities[i]->width / 2; entities[i]->collidedLeft = true; entities[j]->collidedRight = true; } } else if (xDiff < 0) { if (!entities[j]->collidedRight && collisionLR) { entities[j]->x = entities[i]->x + entities[i]->width / 2 + entities[j]->width / 2; } else { entities[i]->x = entities[j]->x - entities[j]->width / 2 - entities[i]->width / 2; entities[i]->collidedRight = true; entities[j]->collidedLeft = true; } } } else { if (yDiff > 0) { //I is on top entities[i]->y = entities[j]->y + entities[j]->height / 2 + entities[i]->height / 2; entities[j]->velocity_y = (entities[j]->velocity_y + entities[j]->velocity_y) / 2; entities[i]->collidedBottom = true; entities[j]->collidedTop = true; entities[i]->velocity_y = 0; } else if (yDiff < 0) { //J is on top entities[j]->y = entities[i]->y + entities[i]->height / 2 + entities[j]->height / 2; if (!(entities[i]->entityType == Entity::ENTITY_PLAYER && !entities[j]->collidedTop && ((entities[i] == players[0] && keys[controls[0]->EXTEND] && keys[controls[0]->UP]) || (entities[i] == players[1] && keys[controls[1]->EXTEND] && keys[controls[1]->UP])))) { entities[i]->collidedTop = true; entities[j]->collidedBottom = true; } entities[j]->velocity_y = 0; } } } } } //Perform Y calculations and collision with world map entities[i]->y += entities[i]->velocity_y * elapsed; for (int w = 0; w < 5; w++) { worldToTileCoordinates(entities[i]->x + ((float)w - 2) / 5.0f * entities[i]->width, entities[i]->y - entities[i]->height / 2, gridX, gridY); if (levelData[-gridY][gridX] != NO_TILE) { entities[i]->y = gridY * TILE_SIZE + entities[i]->height / 2 + 0.000001f; entities[i]->velocity_y = 0; entities[i]->collidedBottom = true; entities[i]->spawnX = gridX; entities[i]->spawnY = gridY; } worldToTileCoordinates(entities[i]->x + ((float)w - 2) / 5.0f * entities[i]->width, entities[i]->y + entities[i]->height / 2, gridX, gridY); if (levelData[-gridY][gridX] != NO_TILE) { entities[i]->y = (gridY - 1) * TILE_SIZE - entities[i]->height / 2 - 0.000001f; if (entities[i]->velocity_y > 0) entities[i]->velocity_y = 0; entities[i]->collidedTop = true; } } //Perform X calculations and collision with world map entities[i]->x += entities[i]->velocity_x * elapsed; for (int h = 0; h < 5; h++) { worldToTileCoordinates(entities[i]->x - entities[i]->width / 2, entities[i]->y + ((float)h - 2) / 5.0f * entities[i]->height, gridX, gridY); if (levelData[-gridY][gridX] != NO_TILE) { entities[i]->x = (gridX + 1) * TILE_SIZE + entities[i]->width / 2 - 0.000001f; entities[i]->velocity_x = 0; entities[i]->collidedLeft = true; } worldToTileCoordinates(entities[i]->x + entities[i]->width / 2, entities[i]->y + ((float)h - 2) / 5.0f * entities[i]->height, gridX, gridY); if (levelData[-gridY][gridX] != NO_TILE) { entities[i]->x = gridX * TILE_SIZE - entities[i]->width / 2 + 0.0000001f; entities[i]->velocity_x = 0; entities[i]->collidedRight = true; } } //Downward Bound Reset for player if (entities[i]->y - entities[i]->height / 2 < TILE_SIZE * (-LEVEL_HEIGHT + 0.5f)) { if (entities[i]->entityType == entities[i]->ENTITY_PLAYER) { entities[i]->width = TILE_SIZE; entities[i]->height = TILE_SIZE; } entities[i]->y = TILE_SIZE * entities[i]->spawnY + entities[i]->height / 2; entities[i]->x = TILE_SIZE * entities[i]->spawnX + entities[i]->width / 2; entities[i]->velocity_y = 0; } } } if (flag1 && flag2 && flag3) { levelData[6][20] = 255; } else { levelData[6][20] = 2; } GLint lightPositionsUniform = glGetUniformLocation(program->programID, "lightPositions"); GLfloat lightPositions[2 * 2 * 4]; float xDiff = player->x - player2->x; float yDiff = player->y - player2->y; float scale = 1.0f; if (fabs(xDiff) * 0.8f > fabs(yDiff) * 1.4f) { if (fabs(xDiff) > PROJECTION_WIDTH * 1.4f) { scale = PROJECTION_WIDTH * 1.4f / fabs(xDiff); } } else if (fabs(yDiff) > PROJECTION_WIDTH * 0.8f) { scale = PROJECTION_WIDTH * 0.8f / fabs(yDiff); } for (int i = 0; i < 2; i++) { if (!includePlayer2) { lightPositions[i * 8] = -players[i]->width / 2; lightPositions[i * 8 + 1] = -players[i]->height / 2; lightPositions[i * 8 + 2] = players[i]->width / 2; lightPositions[i * 8 + 3] = -players[i]->height / 2; lightPositions[i * 8 + 4] = -players[i]->width / 2; lightPositions[i * 8 + 5] = players[i]->height / 2; lightPositions[i * 8 + 6] = players[i]->width / 2; lightPositions[i * 8 + 7] = players[i]->height / 2; break; } else { lightPositions[i * 8] = (-players[i]->width / 2 - (i - 0.5f) * (xDiff)) * scale; lightPositions[i * 8 + 1] = (-players[i]->height / 2 - (i - 0.5f) * (yDiff)) * scale; lightPositions[i * 8 + 2] = (players[i]->width / 2 - (i - 0.5f) * (xDiff)) * scale; lightPositions[i * 8 + 3] = (-players[i]->height / 2 - (i - 0.5f) * (yDiff)) * scale; lightPositions[i * 8 + 4] = (-players[i]->width / 2 - (i - 0.5f) * (xDiff)) * scale; lightPositions[i * 8 + 5] = (players[i]->height / 2 - (i - 0.5f) * (yDiff)) * scale; lightPositions[i * 8 + 6] = (players[i]->width / 2 - (i - 0.5f) * (xDiff)) * scale; lightPositions[i * 8 + 7] = (players[i]->height / 2 - (i - 0.5f) * (yDiff)) * scale; } } glUniform2fv(lightPositionsUniform, 8, lightPositions); }
void ClassDemoApp::UpdateGameLevel(float elapsed) { const Uint8 *keys = SDL_GetKeyboardState(NULL); player->velocity_x = 5.0f; if (keys[SDL_SCANCODE_LEFT]) { player->acceleration_x = -10.0f; } else if (keys[SDL_SCANCODE_RIGHT]) { player->acceleration_x = 10.0f; } else { player->acceleration_x = 0.0f; } if (keys[SDL_SCANCODE_UP] && player->velocity_y < 10.0f) { Mix_PlayChannel(-1, someSound, 0); player->velocity_y += 1.5f; player->collidedBottom = false; } for (size_t i = 0; i < enemies.size(); i++) { enemies[i].Update(elapsed); int gridX = 0, gridY = 0; worldToTileCoordinates(enemies[i].position_x - enemies[i].width / 2, enemies[i].position_y, &gridX, &gridY); if (checkIfSolid(gridX, gridY, levelData)) { enemies[i].velocity_y *= -1; } worldToTileCoordinates(enemies[i].position_x + enemies[i].width / 2, enemies[i].position_y, &gridX, &gridY); if (checkIfSolid(gridX, gridY, levelData)) { enemies[i].velocity_y *= -1; } worldToTileCoordinates(enemies[i].position_x, enemies[i].position_y + enemies[i].height / 2, &gridX, &gridY); if (checkIfSolid(gridX, gridY, levelData)) { enemies[i].velocity_y *= -1; } worldToTileCoordinates(enemies[i].position_x, enemies[i].position_y - enemies[i].height / 2, &gridX, &gridY); if (checkIfSolid(gridX, gridY, levelData)) { enemies[i].velocity_y *= -1; } float ydiff = enemies[i].position_y - player->position_y; float xdiff = enemies[i].position_x - player->position_x; if (xdiff < 5.0f) { enemies[i].position_y -= ydiff / 100.0f; enemies[i].position_x -= xdiff / 100.0f; } } for (size_t i = 0; i < entities.size(); i++) { if (!entities[i]->isStatic) { entities[i]->Update(elapsed); int gridX = 0, gridY = 0; worldToTileCoordinates(entities[i]->position_x - entities[i]->width / 2, entities[i]->position_y, &gridX, &gridY); if (checkIfSolid(gridX, gridY, levelData)) { entities[i]->position_x = (gridX + 1) * TILE_SIZE + entities[i]->width / 2 + 0.005f; entities[i]->velocity_x = 0; entities[i]->collidedLeft = true; } worldToTileCoordinates(entities[i]->position_x + entities[i]->width / 2, entities[i]->position_y, &gridX, &gridY); if (checkIfSolid(gridX, gridY, levelData)) { entities[i]->position_x = gridX * TILE_SIZE - entities[i]->width / 2 - 0.005f; entities[i]->velocity_x = 0; entities[i]->collidedRight = true; } worldToTileCoordinates(entities[i]->position_x, entities[i]->position_y + entities[i]->height / 2, &gridX, &gridY); if (checkIfSolid(gridX, gridY, levelData)) { entities[i]->position_y = (-gridY - 1) * TILE_SIZE - entities[i]->height / 2 - 0.005f; entities[i]->velocity_y = 0; entities[i]->collidedTop = true; } worldToTileCoordinates(entities[i]->position_x, entities[i]->position_y - entities[i]->height / 2, &gridX, &gridY); if (checkIfSolid(gridX, gridY, levelData)) { entities[i]->position_y = -gridY * TILE_SIZE + entities[i]->height / 2 + 0.005f; entities[i]->velocity_y = 0; entities[i]->collidedBottom = true; } } for (Entity& enemy : enemies) { if (enemy.active) { if (player->collidesWith(enemy)) { RenderGameOver(); } } } for (Entity& key : keyv) { if (key.active) { if (player->collidesWith(key)) { score++; key.active = false; } } } } }