C++ 需要帮助优化C++;
我在GameBoyAdvance上编写了一个简单的自上而下的汽车驾驶游戏,类似于第一款GTA。我只使用了矢量图形,而GBA并不能很好地处理它;基本上有5个行人实例,它滞后 我在优化代码方面没有太多经验,所以我想知道我是否可以对代码进行一些调整,以使其运行更快,而不是依赖于它在GBA上运行的事实 我使用的碰撞测试是SAT(分离轴定理),因为我发现它是最容易使用矢量图形进行碰撞检查的测试;这个游戏本身很简单 代码如下:C++ 需要帮助优化C++;,c++,optimization,collision-detection,game-physics,C++,Optimization,Collision Detection,Game Physics,我在GameBoyAdvance上编写了一个简单的自上而下的汽车驾驶游戏,类似于第一款GTA。我只使用了矢量图形,而GBA并不能很好地处理它;基本上有5个行人实例,它滞后 我在优化代码方面没有太多经验,所以我想知道我是否可以对代码进行一些调整,以使其运行更快,而不是依赖于它在GBA上运行的事实 我使用的碰撞测试是SAT(分离轴定理),因为我发现它是最容易使用矢量图形进行碰撞检查的测试;这个游戏本身很简单 代码如下: /* GTA Vector City Author: Alberto Taiut
/*
GTA Vector City
Author: Alberto Taiuti
Version: 2.0
*/
#include "Global.h"
#include <string.h>
#include <cstdio>
#include "font.h"
#include "CVector2D.h"
#include "CCar.h"
#include "CPed.h"
#include <vector>
#include <memory>
/* GLOBAL VARIABLES */
void CheckCollisionsRect(CRect *test_a, CRect *test_b);
std::vector<CVector2D> PrepVectors(CRect *shape);
CVector2D GetMinMaxShape(std::vector<CVector2D> vect_shape, CVector2D axis);
void CheckCollisionRectVSPoint(CRect *test_a, CVector2D *point);
/* MAIN */
// The entry point for the game
int main()
{
// Frame counter
uint32_t frames = 0;
// Previous & current buttons states
static uint16_t prev_buttons = 0, cur_buttons = 0;
// Put the display into bitmap mode 3, and enable background 2.
REG_DISPCNT = MODE4 | BG2_ENABLE;
// Set up the palette.
SetPaletteBG(BLACK, RGB(0, 0, 0)); // black
SetPaletteBG(WHITE, RGB(31, 31, 31)); // white
SetPaletteBG(GREY, RGB(15, 15, 15)); // grey
SetPaletteBG(RED, RGB(31, 0, 0)); // red
SetPaletteBG(GREEN, RGB(0, 31, 0)); // green
SetPaletteBG(BLUE, RGB(0, 0, 31)); // blue
// Create car instance
CCar *car = new CCar(50,50);
// Create a building
/*CRect *test_b = new CRect(100.0f, 100.0f, 30, 30);
CRect *test_c = new CRect(120.0f, 120.0f, 30, 30);
CRect *test_d = new CRect(30.0f, 30.0f, 30, 30);*/
// Pedestrian instances
int ped_number = 10; // Number of pedestrians
std::vector<CPed*> peds; // Ped. entities container (made of smart pointers)
typedef std::vector<CPed*>::iterator p_itor; // Iterator
for(int i = 1; i <= ped_number; i++)
{
peds.push_back(new CPed(i, RED, 2.0f));
}
// Check whether the game is over
bool end = false;
// Main loop
while (!end)
{
// Flip the screen
FlipBuffers();
//Clear the screen
ClearScreen8(BLACK);
// Update frame counter
frames ++;
// Get the current state of the buttons.
cur_buttons = REG_KEYINPUT;
// Handle Input
car->HandleInput(prev_buttons, cur_buttons);
// Logic
car->Update();
for(int i = 0; i < ped_number; i++)
{
peds[i]->Update();
}
for(int i = 0; i < ped_number; i++)
{
CheckCollisionRectVSPoint(car->shape, peds[i]->pos);
}
/*CheckCollisionsRect(car->shape, test_b);
CheckCollisionsRect(car->shape, test_c);
CheckCollisionsRect(car->shape, test_d);
CheckCollisionRectVSPoint(car->shape, test_ped->pos);*/
// Render
car->Draw();
for(int i = 0; i < ped_number; i++)
{
peds[i]->Draw();
}
/*test_b->DrawFrame8(GREEN);
test_c->DrawFrame8(WHITE);
test_d->DrawFrame8(RED);
test_ped->Draw();*/
prev_buttons = cur_buttons;
// VSync
WaitVSync();
}
// Free memory
delete car;
//delete test_b; delete test_c; delete test_d;
//delete test_ped;
for(p_itor itor = peds.begin(); itor != peds.end(); itor ++)// Delete pedestrians
{
peds.erase(itor);
}
return 0;
}
void CheckCollisionsRect(CRect *test_a, CRect *test_b)
{
// If the two shapes are close enough, check for collision, otherways skip and save calculations to the CPU
//if((pow((test_a->points[0]->x - test_b->points[0]->x), 2) + pow((test_a->points[0]->y - test_b->points[0]->y), 2)) < 25.0f)
{
// Prepare the normals for both shapes
std::vector<CVector2D> normals_a = test_a->GetNormalsAsArray();
std::vector<CVector2D> normals_b = test_b->GetNormalsAsArray();
// Create two containers for holding the various vectors used for collision check
std::vector<CVector2D> vect_test_a = PrepVectors(test_a);
std::vector<CVector2D> vect_test_b = PrepVectors(test_b);
// Get the min and max vectors for each shape for each projection (needed for SAT)
CVector2D result_P1 = GetMinMaxShape(vect_test_a, normals_a[1]); //
CVector2D result_P2 = GetMinMaxShape(vect_test_b, normals_a[1]); //
// If the two objects are not colliding
if(result_P1.y < result_P2.x || result_P2.y < result_P1.x)
{
return;
}
CVector2D result_Q1 = GetMinMaxShape(vect_test_a, normals_a[0]); // First axis couple
CVector2D result_Q2 = GetMinMaxShape(vect_test_b, normals_a[0]); //
if(result_Q1.y < result_Q2.x || result_Q2.y < result_Q1.x)
{
return;
}
CVector2D result_R1 = GetMinMaxShape(vect_test_a, normals_b[1]); //
CVector2D result_R2 = GetMinMaxShape(vect_test_b, normals_b[1]); //
if(result_R1.y < result_R2.x || result_R2.y < result_R1.x)
{
return;
}
CVector2D result_S1 = GetMinMaxShape(vect_test_a, normals_b[0]); // Second axis couple
CVector2D result_S2 = GetMinMaxShape(vect_test_b, normals_b[0]); //
if(result_S1.y < result_S2.x || result_S2.y < result_S1.x)
{
return;
}
// Do something
PlotPixel8(200, 10, WHITE);
PlotPixel8(200, 11, WHITE);
PlotPixel8(200, 12, WHITE);
}
}
// Check for collision between an OOBB and a point
void CheckCollisionRectVSPoint(CRect *test_a, CVector2D *point)
{
// Prepare the normals for the shape
std::vector<CVector2D> normals_a = test_a->GetNormalsAsArray();
// Create a container for holding the various vectors used for collision check
std::vector<CVector2D> vect_test_a = PrepVectors(test_a);
// Get projections for the OOBB (needed for SAT)
CVector2D result_P1 = GetMinMaxShape(vect_test_a, normals_a[1]);
float result_point = point->DotProduct(normals_a[1]);
// If the two objects are not colliding on this axis
if(result_P1.y < result_point || result_point < result_P1.x)
{
return;
}
CVector2D result_Q1 = GetMinMaxShape(vect_test_a, normals_a[0]);
result_point = point->DotProduct(normals_a[0]);
// If the two objects are not colliding on this axis
if(result_Q1.y < result_point || result_point < result_Q1.x)
{
return;
}
// Do something
PlotPixel8(200, 10, WHITE);
PlotPixel8(200, 11, WHITE);
PlotPixel8(200, 12, WHITE);
}
// Returns a container with projection vectors for a given shape
std::vector<CVector2D> PrepVectors(CRect *shape)
{
std::vector<CVector2D> vect;
// Create vectors for projection and load them into the arrays
for( uint16_t i=0; i < 5; i++)
{
// Get global position of vectors and then add them to the array
vect.push_back(shape->GetVectorGlobal(i));
}
return vect;
}
CVector2D GetMinMaxShape(std::vector<CVector2D> vect_shape, CVector2D axis)
{
// Set initial minimum and maximum for shape's projection vectors
float min_proj = vect_shape[1].DotProduct(axis);
float max_proj = vect_shape[1].DotProduct(axis);
// Calculate max and min projection vectors by iterating along all of the corners
for(uint16_t i = 2; i < vect_shape.size(); i ++)
{
float current_proj = vect_shape[i].DotProduct(axis);
// Select minimum projection on axis
if(current_proj < min_proj) // If current projection is smaller than the minimum one
min_proj = current_proj;
// Select maximum projection on axis
if(current_proj > max_proj) // If current projection is greater than the minimum one
max_proj = current_proj;
}
return (CVector2D(min_proj, max_proj)); // Return a vector2D as it is a handy way for returning a couple of values
}
/*
矢量城市
作者:阿尔贝托·泰乌蒂
版本:2.0
*/
#包括“Global.h”
#包括
#包括
#包括“font.h”
#包括“cvectro2d.h”
#包括“CCar.h”
#包括“CPed.h”
#包括
#包括
/*全局变量*/
无效检查冲突报告(正确*测试a,正确*测试b);
标准::矢量预处理矢量(正确*形状);
CVector2D GetMinMaxShape(标准::矢量向量_形,CVector2D轴);
无效检查碰撞点(正确*测试点a,CVector2D*点);
/*主要*/
//游戏的切入点
int main()
{
//帧计数器
uint32_t帧=0;
//以前和当前按钮状态
静态uint16上一个按钮=0,当前按钮=0;
//将显示器置于位图模式3,并启用背景2。
REG_DISPCNT=模式4 | BG2_启用;
//设置调色板。
SetPaletteBG(黑色,RGB(0,0,0));//黑色
SetPaletteBG(白色,RGB(31,31,31));//白色
SetPaletteBG(灰色,RGB(15,15,15));//灰色
SetPaletteBG(红色,RGB(31,0,0));//红色
SetPaletteBG(绿色,RGB(0,31,0));//绿色
SetPaletteBG(蓝色,RGB(0,0,31));//蓝色
//创建汽车实例
综合资本分析及审查*car=新的综合资本分析及审查(50,50);
//创建一个建筑
/*正确*测试b=新的正确(100.0f、100.0f、30、30);
正确*测试c=新的正确(120.0f、120.0f、30、30);
正确*测试d=新的正确(30.0f,30.0f,30,30)*/
//行人实例
int ped_number=10;//行人数量
std::vector peds;//Ped.entities容器(由智能指针组成)
typedef std::vector::迭代器p_itor;//迭代器
用于(int i=1;i手动输入(上一个按钮、当前按钮);
//逻辑
汽车->更新();
对于(int i=0;iUpdate();
}
对于(int i=0;i形状,peds[i]->pos);
}
/*检查碰撞反应(汽车->形状,测试b);
检查碰撞反应(汽车->形状,测试c);
检查碰撞反应(汽车->形状,测试d);
检查碰撞点(车辆->形状,测试->位置)*/
//渲染
car->Draw();
对于(int i=0;iDraw();
}
/*测试b->DrawFrame8(绿色);
测试c->DrawFrame8(白色);
测试->牵引架8(红色);
测试->绘制()*/
上一个按钮=当前按钮;
//垂直同步
WaitVSync();
}
//空闲内存
删除汽车;
//删除测试b;删除测试c;删除测试d;
//删除测试用例;
for(p_itor itor=peds.begin();itor!=peds.end();itor++)//删除行人
{
peds.擦除(itor);
}
返回0;
}
无效检查冲突报告(正确*测试a,正确*测试b)
{
//如果两个形状足够接近,请检查碰撞,否则跳过并将计算保存到CPU
//如果((功率((测试a->点[0]->x-测试b->点[0]->x),2)+功率((测试a->点[0]->y-测试b->点[0]->y),2))<25.0f)
{
//准备两个形状的法线
std::vector normals_a=test_a->getnormalsasray();
std::vector normals_b=test_b->getnormalsasray();
//创建两个容器,用于保存用于碰撞检查的各种向量
std::vector vect_test_a=预向量(test_a);
std::vector vect_test_b=预向量(test_b);
//获取每个投影的每个形状的最小和最大向量(SAT所需)
CVectr2D结果_P1=GetMinMaxShape(向量测试_a,法线_a[1])//
CVectr2D结果_P2=GetMinMaxShape(向量测试_b,法线_a[1])//
//如果两个对象没有碰撞
如果(结果_P1.y<结果_P2.x | |结果_P2.y<结果_P1.x)
{
返回;
}
CVectr2D结果_Q1=GetMinMaxShape(向量测试_a,法线_a[0])//第一对轴
CVectr2D结果_Q2=GetMinMaxShape(向量测试_b,法线_a[0])//
如果(结果_Q1.y<结果_Q2.x |结果_Q2.y<结果_Q1.x)
{
返回;
}
CVectr2D结果_R1=GetMinMaxShape(向量测试_a,法线_b[1])//
CVectr2D结果_R2=GetMinMaxShape(向量测试_b,法线_b[1])//
如果(结果_R1.y<结果_R2.x | |结果_R2.y<结果_R1.x)
{
返回;
}
CVectr2D结果_S1=GetMinMaxShape(向量测试_a,法线_b[0])//第二轴耦合
CVectr2D结果_S2=GetMinMaxShape(向量测试_b,法线_b[0])//
如果(结果_S1.y<结果_S2.x |结果_S2.y<结果_S1.x)
{
返回;
}
//做点什么
PlotPixel8(200,10,白色);
PlotPixel8(200,11,白色);
PlotPixel8(200,12,白色);
}
}
//检查OOBB和点之间的碰撞
无效检查碰撞点(正确*测试点a,CVector2D*点)
{
//准备形状的法线
std::vector normals_a=test_a->getnormalsasray();
//创建一个容器,用于保存用于碰撞检查的各种向量
std::vector vect_test_a=预向量(test_a);
//获取OOBB的投影(SAT需要)
CVectr2D结果_P1=GetMinMaxShape(向量测试_a,法线_a[1]);
浮点结果\点=点->点积(法线\点[1]);
//如果两个对象在此轴上没有碰撞
如果(结果_P1.y<结果_点| |结果_点<结果_P1.x)
{
返回;
}
CVectr2D结果_Q1=GetMinMaxShape(向量测试_a,法线_a[0]);
结果_点=点->点积(法线_a[0]);
//如果两个对象在此轴上没有碰撞
if(结果_Q1.y<结果_点| |结果_点<结果_Q1.x)
{
返回;
}
//做点什么
PlotPixel8(200,10,白色);
PlotPixel8(200,11,白色);
PlotPixel8(200,12,白色);
}
//返回一个包含
for(int i = 0; i < ped_number; i++)
{
CheckCollisionRectVSPoint(car->shape, peds[i]->pos);
}
// Prepare the normals for both shapes
std::vector<CVector2D> normals_a = test_a->GetNormalsAsArray();
// Create two containers for holding the various vectors used for collision check
std::vector<CVector2D> vect_test_a = PrepVectors(test_a);