c ++,qt
现在我正在编写乒乓球比赛的球方向部分。
对我来说,我的想法看起来没问题,但效果并不好。
我的想法是这样的。
par_x,par_y是现在的球位置。 pre_x,pre_y是之前的球位置。
此代码是移动球的部分。
请告诉我错误的想法。 我不知道哪里出错了。它建立得很好,但是球并没有向正确的方向反弹。它移动到其他方式或坚持边界。
此代码为mainwindow.h和mainwindow.cpp
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QCheckBox>
#include <QDebug>
#include <QPainter>
#include <QImage>
#include <QPixmap>
#include <QLabel>
#include <QPalette>
#include <QWidget>
#include <QtEvents>
#include <QPushButton>
#include <QFocusFrame>
#include <QMap>
#include <QString>
#include <QThread>
#include <math.h>
#include <QVector>
class Ball: public QThread
{
Q_OBJECT
private:
int x, y;
int pre_x, pre_y;
int par_x, par_y;
public:
Ball(){x=380; y=490;}
int get_x();
int get_y();
void set_x(int x);
void set_y(int y);
void set_posx(int x, int oper);
void set_posy(int y, int oper);
void oper_switch(int flag);
void direction(int now);
QVector <int> vector_x;
QVector <int> vector_y;
QVector <int> :: iterator it;
protected:
void run();
signals:
int sig();
};
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
QImage *img_bar, *img_ball, *img_background, *img_GameBack;
QPixmap *buf_bar, *buf_ball, *buf_background, *buf_GameBack ;
QLabel *lbl_bar, *lbl_ball, *lbl_background, *lbl_GameBack ;
QWidget *backWidget;
Ball *ball;
QPushButton *btn[3];
private slots:
void btn_click();
void ball_move();
protected:
virtual void keyPressEvent(QKeyEvent *event);
virtual void keyReleaseEvent(QKeyEvent *event);
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
int bar_x = 350; // Bar
const int bar_y = 500;
int btn_y = 350; // Button position
int key_flag = 0;
int oper_flag = 0;
int bar_ball = 0;
int t = 0;
MainWindow::MainWindow(QWidget *parent)
{
ball = new Ball();
img_background = new QImage();
buf_background = new QPixmap();
if(img_background->load("C://Users//user//Documents//BreaOut//Background.png"))
{
*buf_background = QPixmap::fromImage(*img_background);
*buf_background = buf_background->scaled(800,600);
}
else
{
qDebug("Image can't find.");
}
lbl_background = new QLabel(this);
lbl_background->setPixmap(*buf_background);
lbl_background->resize(buf_background->width(),buf_background->height());
lbl_background->move(0,0);
lbl_background->show();
for(int i = 0; i < 2; i++)
{
switch(i)
{
case 0 :
{
btn[i] = new QPushButton(QString("Game Start").arg(i), this);
break;
}
case 1 :
{
btn[i] = new QPushButton(QString("How to play game?").arg(i), this);
break;
}
}
btn[i] -> setGeometry(325, btn_y, 150, 40);
btn_y += 50;
}
connect(btn[0], SIGNAL(clicked()), this, SLOT(btn_click()));
img_GameBack = new QImage();
buf_GameBack = new QPixmap();
if(img_GameBack->load("C://Users//user//Documents//BreaOut//GameBack.png"))
{
*buf_GameBack = QPixmap::fromImage(*img_GameBack);
*buf_GameBack = buf_GameBack->scaled(800,600); // 이미지 크기 조정
}
else
{
qDebug("Image can't find.");
}
lbl_GameBack = new QLabel(this);
lbl_GameBack->setPixmap(*buf_GameBack);
lbl_GameBack->resize(buf_GameBack->width(),buf_GameBack->height());
lbl_GameBack->move(0,0);
lbl_GameBack->setVisible(false);
/*! 바 이미지 삽입*/
img_bar = new QImage();
buf_bar = new QPixmap();
if(img_bar->load("C://Users//user//Documents//BreaOut//bar.png"))
{
*buf_bar = QPixmap::fromImage(*img_bar);
*buf_bar = buf_bar->scaled(80,18); // 이미지 크기 조정
}
else
{
qDebug("Image can't find.");
}
lbl_bar = new QLabel(this);
lbl_bar->setPixmap(*buf_bar);
lbl_bar->resize(buf_bar->width(),buf_bar->height());
lbl_bar->move(bar_x, bar_y);
// lbl_bar->show();
lbl_bar->setVisible(false);
img_ball = new QImage();
buf_ball = new QPixmap();
if(img_ball->load("C://Users//user//Documents//BreaOut//Ball.png"))
{
*buf_ball = QPixmap::fromImage(*img_ball);
*buf_ball = buf_ball->scaled(12,12); // 이미지 크기 조정
}
else
{
qDebug("Image can't find.");
}
lbl_ball = new QLabel(this);
lbl_ball->setVisible(false); connect(ball, SIGNAL(sig()), this, SLOT(ball_move()));
lbl_ball->setPixmap(*buf_ball);
lbl_ball->resize(buf_ball->width(),buf_ball->height());
lbl_ball->move(ball->get_x(), ball->get_y());
lbl_ball->show();
lbl_ball->setVisible(false);
connect(ball, SIGNAL(sig()), this, SLOT(ball_move()));
QString brk1, brk2, brk3;
brk1 = "X://parkjh688//Breakout//Brick1.png";
brk2 = "X://parkjh688//Breakout//Brick2.png";
brk3 = "X://parkjh688//Breakout//Brick3.png";
/* QMap<QString, QMap<int, int> > m1 = { {brk1,1,1}, {brk1,1,1}, {brk1,1,1}, {brk1,1,1}, {brk1,1,1}, {brk1,1,1},
{brk2,1,1}, {brk2,1,1}, {brk2,1,1}, {brk2,1,1}, {brk2,1,1}, {brk2,1,1},
{brk3,1,1}, {brk3,1,1}, {brk3,1,1}, {brk3,1,1}, {brk3,1,1}, {brk3,1,1}};
QMap<QString, QMap<int, int> > :: iterator it1;
QMap<int, int> :: iterator it2;
for(it1=m.begin(); it1 != m.end() ; it1++)
{
}*/
// for( it1 = m.begin() ; it1 != m.end() ; it1++)
setWindowTitle("BreakOut");
setFixedSize(800, 600);
}
MainWindow::~MainWindow()
{
}
void MainWindow::btn_click()
{
lbl_background->setVisible(false);
lbl_GameBack->setVisible(true);
for(int i = 0; i < 2; i++)
{
btn[i]->setVisible(false);
}
lbl_bar->setVisible(true);
lbl_ball->setVisible(true);
key_flag = 1;
}
void MainWindow::keyPressEvent(QKeyEvent *event)
{
Q_UNUSED(event);
qDebug("Key Press Event.");
if(key_flag == 1){
switch(event->key())
{
case Qt::Key_A: // A가 눌렸을 때
if( bar_x > 0)
{
bar_x -=20; // lbl_bar를 움직이기 위한 좌표 변경
qDebug() << bar_x;
if(bar_ball == 0)
{
ball->set_posx(20,1);
lbl_ball->move(ball->get_x(),ball->get_y());
lbl_bar->move(bar_x,bar_y);
}
lbl_bar->move(bar_x,bar_y);
}
lbl_bar->show();
break;
case Qt::Key_D: // D가 눌렸을 때
if( bar_x < 720)
{
bar_x+=20;
if(bar_ball == 0)
{
ball->set_posx(20,0);
lbl_ball->move(ball->get_x(),ball->get_y());
lbl_bar->move(bar_x,bar_y);
}
lbl_bar->move(bar_x,bar_y);
}
lbl_bar->show(); break;
break;
case Qt::Key_W:
ball->start();
bar_ball = 1;
break;
default:
break;
}
}
}
void MainWindow::keyReleaseEvent(QKeyEvent*event)
{
Q_UNUSED(event);
}
void MainWindow::ball_move()
{
lbl_ball->move(ball->get_x(), ball->get_y());
lbl_ball->show();
}
int Ball::get_x(){ return x; }
int Ball::get_y(){ return y; }
/* oper 0 : +=
* oper 1 : -= */
void Ball::set_posx(int x, int oper)
{
switch(oper)
{
case 0: this->x += x; break;
case 1: this->x -= x; break;
}
}
void Ball::set_posy(int y, int oper)
{
switch(oper)
{
case 0: this->y += y; break;
case 1: this->y -= y; break;
}
}
void Ball::run()
{
bool stop = false;
int now = 0;
int lock = 1;
while(!stop)
{
vector_x.push_back(x);
vector_y.push_back(y);
/* for(it = vector_x.begin(); it != vector_x.end(); it++)
qDebug() << "x:" << (*it);
for(it = vector_y.begin(); it != vector_y.end(); it++)
qDebug() << "Y:" << (*it);*/
if(y < 5)
{
// oper_flag = 1;
// oper_switch(oper_flag);
now = 3;
it = vector_x.end();
it -= 2;
pre_x = (*it);
par_x = x;
// qDebug() << "pre_x: " << pre_x;
// qDebug() << "X : " << x;
it = vector_y.end();
it -= 2;
pre_y = (*it);
par_y = y;
// qDebug() << "pre_y: " << pre_y;
// qDebug() << "Y : " << y;
}
else if( ((bar_x < x) && (x < bar_x+80)) &&
((bar_y < y) && (y < bar_y+30)) )
{
//oper_flag = 0;
now = 4;
it = vector_x.end();
it -= 2;
pre_x = (*it);
par_x = x;
qDebug() << "pre_x: " << pre_x;
qDebug() << "X : " << x;
it = vector_y.end();
it -= 2;
pre_y = (*it);
par_y = y;
qDebug() << "pre_y: " << pre_y;
qDebug() << "Y : " << y;
qDebug() << "Bar Collision.";
}
else if(x > 785)
{
//oper_flag = 3;
now = 2;
it = vector_x.end();
it -= 2;
pre_x = (*it);
par_x = x;
qDebug() << "pre_x: " << pre_x;
qDebug() << "X : " << x;
it = vector_y.end();
it -= 2;
pre_y = (*it);
par_y = y;
qDebug() << "pre_y: " << pre_y;
qDebug() << "Y : " << y;
}
else if(x < 0)
{
//oper_flag = 3;
now = 1;
it = vector_x.end();
it -= 2;
pre_x = (*it);
par_x = x;
qDebug() << "pre_x: " << pre_x;
qDebug() << "X : " << x;
it = vector_y.end();
it -= 2;
pre_y = (*it);
par_y = y;
qDebug() << "pre_y: " << pre_y;
qDebug() << "Y : " << y;
lock = 0;
}
else if( y > 580)
{
stop = true;
qDebug() << "Thread Finish.";
}
//oper_switch(oper_flag);
direction(now);
sig();
msleep(20);
}
}
void Ball::set_x(int x) { this->x = x; }
void Ball::set_y(int y) { this->y = y; }
void Ball::direction(int now)
{
float theta, r;
theta = atan2( (float)(par_y-pre_y), (float)(par_x-pre_x) ) *180 / 3.1415f;
qDebug() << r;
if(now == 0)
{
x += 2;
y -= 5;
}
else if(now == 1)
{
if( (par_x<pre_x) && (par_y<pre_y) )
{
x += sin(theta)*10;
y -= cos(theta)*10;
}
else if( (par_x<pre_x) && (par_y>pre_y) )
{
x += sin(theta)*3;
y += cos(theta)*3;
}
}
else if(now == 2)
{
// vector_x.clear();
// vector_y.clear();
if( (par_x>pre_x) && (par_y>pre_y) ) // |
{ // \/
x -= sin(theta)*10;
y += cos(theta)*10;
}
else if( (par_x>pre_x) && (par_y<pre_y) )
{
x -= sin(theta)*10;
y -= cos(theta)*10;
}
}
else if(now == 3)
{
if( (par_x>pre_x) && (par_y<pre_y) ) // ->
{
x += cos(theta)*10;
y += sin(theta)*10;
}
else if( (par_x<pre_x) && (par_y<pre_y)) // <-
{
x -= cos(theta)*10;
y += sin(theta)*10;
}
}
else // now == 4
{
// vector_x.clear();
// vector_y.clear();
if( (par_x>pre_x) && (par_y>pre_y) ) // ->
{
x += cos(theta)*10;
y -= sin(theta)*10;
}
else if( (par_x<pre_x) && (par_y>pre_y) )
{
x -= cos(theta)*10;
y -= sin(theta)*10;
}
}
}
/*
void Ball::oper_switch(int flag)
{
float theta;
it = vector_x.end();
it -= 2;
qDebug() << (*it);
pre_x = (*it);
it = vector_y.end();
//pre_y = vector_y.at(it--);
// theta = atan2( (float)(y-pre_y), (float)(x-pre_x) ) *180 / 3.1415f;
switch(flag)
{
case 0:
y -= 2, x += 2;
break;
case 1:
y += 2; x += 2;
theta = atan2( (float)(y-pre_y), (float)(x-pre_x) ) *180 / 3.1415f;
x += cos(theta);
y -= sin(theta);
break;
case 3:
y -= 2; x-=2; break;
}
}*/
答案 0 :(得分:1)
不知道这会回答你的问题有多好,但我不能很好地掌握你在这里想做什么,因为你的代码中没有任何评论,也不能隐式运行你的代码,因为我需要所有的库和你正在使用的任何东西,这对我来说太过分了。
但是,您是否考虑过从不同角度重新训练整个球的运动?看起来你正在做很多不必要的工作来移动那个球,你为什么不把它当作笛卡尔网格系统的一个点呢?例如:
double x; //position of ball on x axis, global variable
double y; //position of ball on y axis, global variable
double speed = 1; //speed of ball, global variable
void move()
{
//the operation below will move the ball in a 45 degree angle to the
//top-right for every drawn frame
x += speed;
y += speed;
}
此外,你也可以用这种方式改变球的方向,只需根据球朝向的当前象限改变x和y的增量值。例如,在示例中,球将在象限1中行进,并且将其发送到左下方,它将在象限3的方向上。只需确保x和y的速度之和保持相同。数字,否则球将根据角度的大小加速/减速。
希望这会有所帮助:)