init
This commit is contained in:
commit
de44ead6db
12
.gitignore
vendored
Executable file
12
.gitignore
vendored
Executable file
@ -0,0 +1,12 @@
|
|||||||
|
*~
|
||||||
|
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
*.pro.user.*
|
||||||
|
*.pro.user
|
||||||
|
|
||||||
|
build-*/
|
||||||
|
*.app
|
||||||
|
*.exe
|
||||||
|
|
||||||
|
build
|
26
Robots.pro
Executable file
26
Robots.pro
Executable file
@ -0,0 +1,26 @@
|
|||||||
|
TEMPLATE = app
|
||||||
|
QT += widgets
|
||||||
|
HEADERS += src/mainwindow.h \
|
||||||
|
src/utilities.h \
|
||||||
|
src/constants.h \
|
||||||
|
src/Unit.h \
|
||||||
|
src/Junk.h \
|
||||||
|
src/Hero.h \
|
||||||
|
src/Robot.h \
|
||||||
|
src/GameState.h \
|
||||||
|
src/qgameoverwindow.h \
|
||||||
|
src/qresetbutton.h
|
||||||
|
SOURCES += src/mainwindow.cpp \
|
||||||
|
src/robotsmain.cpp \
|
||||||
|
src/utilities.cpp \
|
||||||
|
src/Unit.cpp \
|
||||||
|
src/Junk.cpp \
|
||||||
|
src/Hero.cpp \
|
||||||
|
src/Robot.cpp \
|
||||||
|
src/GameState.cpp \
|
||||||
|
src/qgameoverwindow.cpp \
|
||||||
|
src/qresetbutton.cpp
|
||||||
|
QMAKE_CXXFLAGS += -std=c++11
|
||||||
|
macx {
|
||||||
|
cache()
|
||||||
|
}
|
119
src/GameState.cpp
Executable file
119
src/GameState.cpp
Executable file
@ -0,0 +1,119 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (C) David Wolfe, 1999. All rights reserved.
|
||||||
|
* Ported to Qt and adapted for TDDD86, 2015.
|
||||||
|
* Updated for TDDD86, 2021.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "GameState.h"
|
||||||
|
#include "utilities.h"
|
||||||
|
#include "constants.h"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
|
GameState::GameState(int numberOfRobots) {
|
||||||
|
for (int i = 0; i < numberOfRobots; i++) {
|
||||||
|
Robot robot;
|
||||||
|
while(!isEmpty(robot)){
|
||||||
|
robot = Robot();
|
||||||
|
}
|
||||||
|
robots.push_back(robot);
|
||||||
|
}
|
||||||
|
teleportHero();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameState::draw(QGraphicsScene *scene) const {
|
||||||
|
scene->clear();
|
||||||
|
hero.draw(scene);
|
||||||
|
for (const Robot& robot: robots)
|
||||||
|
robot.draw(scene);
|
||||||
|
for (const Junk& junk: junks)
|
||||||
|
junk.draw(scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameState::teleportHero() {
|
||||||
|
do hero.teleport();
|
||||||
|
while (!isEmpty(hero));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameState::moveRobots() {
|
||||||
|
for(Robot& robot: robots)
|
||||||
|
robot.moveTowards(hero.asPoint());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GameState::updateCrashes() {
|
||||||
|
for(unsigned i=0; i < robots.size(); ++i){
|
||||||
|
for(unsigned j=0; j < junks.size(); ++j){
|
||||||
|
if(robots[i].at(junks[j])){
|
||||||
|
robots[i].doCrash();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(unsigned o=i+1; o < robots.size(); ++o){
|
||||||
|
if(robots[i].at(robots[o])){
|
||||||
|
robots[i].doCrash();
|
||||||
|
robots[o].doCrash();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int GameState::countToBeJunked()const{
|
||||||
|
int numberDestroyed =0;
|
||||||
|
for(unsigned i=0; i < robots.size(); ++i)
|
||||||
|
if(robots[i].isToBeJunked())
|
||||||
|
numberDestroyed++;
|
||||||
|
return numberDestroyed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameState::junkTheCrashed(){
|
||||||
|
for(unsigned i=0; i < robots.size(); ++i){
|
||||||
|
if (robots[i].isToBeJunked()) {
|
||||||
|
junks.push_back(Junk(robots[i].asPoint()));
|
||||||
|
robots[i] = robots[robots.size()-1];
|
||||||
|
robots.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GameState::someRobotsAlive() const {
|
||||||
|
for(unsigned i=0; i < robots.size(); ++i)
|
||||||
|
if(robots[i].isAlive())
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool GameState::heroDead() const {
|
||||||
|
for(const Robot& robot: robots){
|
||||||
|
if(hero.at(robot)){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(const Junk& junk: junks){
|
||||||
|
if(hero.at(junk)){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GameState::moveHeroTowards(const Point& dir) {
|
||||||
|
hero.moveTowards(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
Point GameState::getHeroAsPoint() const {return hero.asPoint();}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Free of robots and junk
|
||||||
|
*/
|
||||||
|
bool GameState::isEmpty(const Unit& unit) const {
|
||||||
|
for(const Robot& robot: robots)
|
||||||
|
if(robot.at(unit))
|
||||||
|
return false;
|
||||||
|
for(const Junk& junk: junks)
|
||||||
|
if(junk.at(unit))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
91
src/GameState.h
Executable file
91
src/GameState.h
Executable file
@ -0,0 +1,91 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (C) David Wolfe, 1999. All rights reserved.
|
||||||
|
* Ported to Qt and adapted for TDDD86, 2015.
|
||||||
|
*
|
||||||
|
* Maintains the game state: Location of all robots, junk and hero.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GAMESTATE_H
|
||||||
|
#define GAMESTATE_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <QGraphicsScene>
|
||||||
|
#include "Unit.h"
|
||||||
|
#include "Robot.h"
|
||||||
|
#include "Junk.h"
|
||||||
|
#include "Hero.h"
|
||||||
|
|
||||||
|
class GameState {
|
||||||
|
public:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a GameState with randomly placed, but not
|
||||||
|
* overlapping hero and numberOfRobots robots
|
||||||
|
*/
|
||||||
|
GameState(int numberOfRobots);
|
||||||
|
|
||||||
|
~GameState() = default;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clear and redraw entire playing field
|
||||||
|
*/
|
||||||
|
void draw(QGraphicsScene* scene) const; // Clear and redraw entire playing field
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Teleport hero to random location
|
||||||
|
*/
|
||||||
|
void teleportHero();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Move robots one step towards hero
|
||||||
|
*/
|
||||||
|
void moveRobots();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Identify crashed robots
|
||||||
|
*/
|
||||||
|
void updateCrashes();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Count identified crashed robots
|
||||||
|
*/
|
||||||
|
int countToBeJunked()const;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Replace each identified crashed robot with a junk
|
||||||
|
*/
|
||||||
|
void junkTheCrashed();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Are there still robots that did not crash?
|
||||||
|
*/
|
||||||
|
bool someRobotsAlive() const;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Is hero in same place as robot or junk?
|
||||||
|
*/
|
||||||
|
bool heroDead() const;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Move hero towards dir
|
||||||
|
*/
|
||||||
|
void moveHeroTowards (const Point& dir);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return hero
|
||||||
|
*/
|
||||||
|
Point getHeroAsPoint () const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<Robot> robots; // the robots
|
||||||
|
std::vector<Junk> junks; // robots that have turned to junk
|
||||||
|
Hero hero; // the hero
|
||||||
|
|
||||||
|
// private helpers
|
||||||
|
bool isEmpty(const Unit& unit) const;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // GAMESTATE_H
|
16
src/Hero.cpp
Executable file
16
src/Hero.cpp
Executable file
@ -0,0 +1,16 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (C) David Wolfe, 1999. All rights reserved.
|
||||||
|
* Ported to Qt and adapted for TDDD86, 2015.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Hero.h"
|
||||||
|
#include "constants.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void Hero::draw(QGraphicsScene *scene) const {
|
||||||
|
Point corner = asPoint();
|
||||||
|
scene->addRect(QRectF(corner.x * UNIT_WIDTH, corner.y * UNIT_HEIGHT,
|
||||||
|
UNIT_WIDTH, UNIT_HEIGHT), Qt::NoPen, QBrush(HERO_COLOR));
|
||||||
|
}
|
||||||
|
|
23
src/Hero.h
Executable file
23
src/Hero.h
Executable file
@ -0,0 +1,23 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (C) David Wolfe, 1999. All rights reserved.
|
||||||
|
* Ported to Qt and adapted for TDDD86, 2015.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HERO_H
|
||||||
|
#define HERO_H
|
||||||
|
|
||||||
|
#include "Unit.h"
|
||||||
|
#include <QGraphicsScene>
|
||||||
|
|
||||||
|
class Hero : public Unit {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Draws this hero onto the given QGraphicsScene.
|
||||||
|
*/
|
||||||
|
void draw(QGraphicsScene *scene) const;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // HERO_H
|
16
src/Junk.cpp
Executable file
16
src/Junk.cpp
Executable file
@ -0,0 +1,16 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (C) David Wolfe, 1999. All rights reserved.
|
||||||
|
* Ported to Qt and adapted for TDDD86, 2015.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Junk.h"
|
||||||
|
#include "constants.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void Junk::draw(QGraphicsScene *scene) const {
|
||||||
|
Point corner = asPoint();
|
||||||
|
scene->addEllipse(QRectF(corner.x * UNIT_WIDTH, corner.y * UNIT_HEIGHT,
|
||||||
|
JUNK_RADIUS, JUNK_RADIUS), QPen(), QBrush(JUNK_COLOR));
|
||||||
|
}
|
22
src/Junk.h
Executable file
22
src/Junk.h
Executable file
@ -0,0 +1,22 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (C) David Wolfe, 1999. All rights reserved.
|
||||||
|
* Ported to Qt and adapted for TDDD86, 2015.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef JUNK_H
|
||||||
|
#define JUNK_H
|
||||||
|
|
||||||
|
#include "Unit.h"
|
||||||
|
#include <QGraphicsScene>
|
||||||
|
|
||||||
|
class Junk : public Unit {
|
||||||
|
public:
|
||||||
|
Junk(const Point& p): Unit(p){}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Draws this junk onto the given QGraphicsScene.
|
||||||
|
*/
|
||||||
|
void draw(QGraphicsScene* scene) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // JUNK_H
|
29
src/Robot.cpp
Executable file
29
src/Robot.cpp
Executable file
@ -0,0 +1,29 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (C) David Wolfe, 1999. All rights reserved.
|
||||||
|
* Ported to Qt and adapted for TDDD86, 2015.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Robot.h"
|
||||||
|
#include "constants.h"
|
||||||
|
|
||||||
|
bool Robot::isAlive() const{
|
||||||
|
return !toBeJunked;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Robot::doCrash(){
|
||||||
|
toBeJunked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Robot::isToBeJunked() const{
|
||||||
|
return toBeJunked;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Robot::draw(QGraphicsScene *scene) const {
|
||||||
|
Point corner = asPoint();
|
||||||
|
scene->addEllipse(QRectF(corner.x * UNIT_WIDTH, corner.y * UNIT_HEIGHT,
|
||||||
|
JUNK_RADIUS, JUNK_RADIUS), QPen(), QBrush(ROBOT_COLOR));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
41
src/Robot.h
Executable file
41
src/Robot.h
Executable file
@ -0,0 +1,41 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (C) David Wolfe, 1999. All rights reserved.
|
||||||
|
* Ported to Qt and adapted for TDDD86, 2015.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ROBOT_H
|
||||||
|
#define ROBOT_H
|
||||||
|
|
||||||
|
#include "Unit.h"
|
||||||
|
#include <QGraphicsScene>
|
||||||
|
|
||||||
|
class Robot : public Unit {
|
||||||
|
bool toBeJunked = false;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* did not crash yet
|
||||||
|
*/
|
||||||
|
bool isAlive() const;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Crashes and remembers it
|
||||||
|
*/
|
||||||
|
void doCrash();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return whether the robot crashed
|
||||||
|
*/
|
||||||
|
bool isToBeJunked() const;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Draws this robot onto the given QGraphicsScene.
|
||||||
|
*/
|
||||||
|
void draw(QGraphicsScene* scene) const;
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ROBOT_H
|
59
src/Unit.cpp
Executable file
59
src/Unit.cpp
Executable file
@ -0,0 +1,59 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (C) David Wolfe, 1999. All rights reserved.
|
||||||
|
* Ported to Qt and adapted for TDDD86, 2015.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Unit.h"
|
||||||
|
#include "constants.h"
|
||||||
|
#include "utilities.h"
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
Unit::Unit() {
|
||||||
|
teleport();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Unit::Unit(const Point& p) {
|
||||||
|
x = p.x;
|
||||||
|
y = p.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
Point Unit::asPoint() const {
|
||||||
|
return Point{x, y};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Unit::at(const Unit& u) const {
|
||||||
|
return (x == u.x && y == u.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void Unit::moveTowards(const Point& p) {
|
||||||
|
if (x > p.x) x--;
|
||||||
|
if (x < p.x) x++;
|
||||||
|
if (y > p.y) y--;
|
||||||
|
if (y < p.y) y++;
|
||||||
|
checkBounds();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Unit::teleport() {
|
||||||
|
x = rand_int (MIN_X, MAX_X);
|
||||||
|
y = rand_int (MIN_Y, MAX_Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
double Unit::distanceTo(const Unit& u) const {
|
||||||
|
double dx = u.x - x;
|
||||||
|
double dy = u.y - y;
|
||||||
|
return sqrt(dx * dx + dy * dy);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Put this unit inside playing field if outside
|
||||||
|
*/
|
||||||
|
void Unit::checkBounds() {
|
||||||
|
if (x < MIN_X) x = MIN_X;
|
||||||
|
if (x > MAX_X) x = MAX_X;
|
||||||
|
if (y < MIN_Y) y = MIN_Y;
|
||||||
|
if (y > MAX_Y) y = MAX_Y;
|
||||||
|
}
|
65
src/Unit.h
Executable file
65
src/Unit.h
Executable file
@ -0,0 +1,65 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (C) David Wolfe, 1999. All rights reserved.
|
||||||
|
* Ported to Qt and adapted for TDDD86, 2015.
|
||||||
|
* Updated for TDDD86, 2021.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef UNIT_H
|
||||||
|
#define UNIT_H
|
||||||
|
|
||||||
|
#include "utilities.h"
|
||||||
|
#include <QGraphicsScene>
|
||||||
|
|
||||||
|
/* Root class for all pieces on the board.
|
||||||
|
* Subclasses are Robot, Hero and Junk.
|
||||||
|
*/
|
||||||
|
class Unit {
|
||||||
|
public:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a unit at a random position
|
||||||
|
*/
|
||||||
|
Unit();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create unit at given point
|
||||||
|
*/
|
||||||
|
Unit(const Point& p);
|
||||||
|
|
||||||
|
virtual ~Unit(){}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return Point representation of Unit
|
||||||
|
*/
|
||||||
|
Point asPoint() const;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Am I in the same square as u?
|
||||||
|
*/
|
||||||
|
bool at(const Unit& u) const;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Take one step closer to point
|
||||||
|
*/
|
||||||
|
void moveTowards(const Point&);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Teleport. Does not check for collision
|
||||||
|
*/
|
||||||
|
void teleport();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Euclidean distance to u
|
||||||
|
*/
|
||||||
|
double distanceTo(const Unit& u) const;
|
||||||
|
private:
|
||||||
|
int x; // x position of this unit
|
||||||
|
int y; // y position of this unit
|
||||||
|
|
||||||
|
// private helpers
|
||||||
|
void checkBounds();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // UNIT_H
|
32
src/constants.h
Executable file
32
src/constants.h
Executable file
@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (C) David Wolfe, 1999. All rights reserved.
|
||||||
|
* Ported to Qt and adapted for TDDD86, 2015.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CONSTANTS_H
|
||||||
|
#define CONSTANTS_H
|
||||||
|
|
||||||
|
#include <QColor>
|
||||||
|
|
||||||
|
// GUI constants
|
||||||
|
const int MIN_X = 0;
|
||||||
|
const int MIN_Y = 0;
|
||||||
|
const int MAX_X = 39;
|
||||||
|
const int MAX_Y = 39;
|
||||||
|
const int UNIT_WIDTH = 10;
|
||||||
|
const int UNIT_HEIGHT = 10;
|
||||||
|
static const int SCENE_WIDTH = 400;
|
||||||
|
static const int SCENE_HEIGHT = 400;
|
||||||
|
const int JUNK_RADIUS = 9;
|
||||||
|
const QColor JUNK_COLOR = QColor(0, 0, 0);
|
||||||
|
const QColor ROBOT_COLOR = QColor(245, 95, 60);
|
||||||
|
const QColor HERO_COLOR = QColor(237, 207, 114);
|
||||||
|
|
||||||
|
// game constants
|
||||||
|
const int MIN_ROBOTS = 10;
|
||||||
|
const int MAX_ROBOTS = 80;
|
||||||
|
const int ROBOTS_INC = 5; // Additional robots per round
|
||||||
|
const int POINTS_PER_ROBOT = 10;
|
||||||
|
const int WAIT_BONUS = 20; // Per robot
|
||||||
|
|
||||||
|
#endif // CONSTANTS_H
|
201
src/mainwindow.cpp
Executable file
201
src/mainwindow.cpp
Executable file
@ -0,0 +1,201 @@
|
|||||||
|
/**
|
||||||
|
* TDDD86 Robots
|
||||||
|
* This file contains the implementation of the mainwindow class.
|
||||||
|
* See mainwindow.h for comments about each member.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include "mainwindow.h"
|
||||||
|
#include "Hero.h"
|
||||||
|
#include "Robot.h"
|
||||||
|
#include "Junk.h"
|
||||||
|
|
||||||
|
MainWindow::MainWindow(QWidget *parent) :
|
||||||
|
QWidget(parent) {
|
||||||
|
// set default size and color
|
||||||
|
scene = new QGraphicsScene(0, 0, SCENE_WIDTH, SCENE_HEIGHT);
|
||||||
|
scene->setBackgroundBrush(QBrush(QColor(204, 192, 179)));
|
||||||
|
view = new QGraphicsView(scene);
|
||||||
|
|
||||||
|
// create the main layout
|
||||||
|
mainLayout = new QVBoxLayout();
|
||||||
|
setLayout(mainLayout);
|
||||||
|
|
||||||
|
// add game board to layout
|
||||||
|
mainLayout->insertWidget(0, view);
|
||||||
|
|
||||||
|
// start new game and draw state
|
||||||
|
gameState.draw(scene);
|
||||||
|
|
||||||
|
// create label layout
|
||||||
|
labelLayout = new QHBoxLayout();
|
||||||
|
|
||||||
|
// create the score widget
|
||||||
|
scoreLabel = new QLabel(QString("SCORE: %1").arg(score));
|
||||||
|
scoreLabel->setStyleSheet("QLabel { color: rgb(235,224,214); font: 16pt; }");
|
||||||
|
scoreLabel->setFixedHeight(35);
|
||||||
|
|
||||||
|
// create the level widget
|
||||||
|
levelLabel = new QLabel(QString("LEVEL: %1").arg(level));
|
||||||
|
levelLabel->setStyleSheet("QLabel { color: rgb(235,224,214); font: 16pt; }");
|
||||||
|
levelLabel->setFixedHeight(35);
|
||||||
|
|
||||||
|
// add score and level widgets to board
|
||||||
|
labelLayout->insertWidget(0, levelLabel, 0, Qt::AlignLeft);
|
||||||
|
labelLayout->insertWidget(1, scoreLabel, 0, Qt::AlignRight);
|
||||||
|
mainLayout->insertLayout(1, labelLayout);
|
||||||
|
|
||||||
|
// style sheet of the game board
|
||||||
|
setStyleSheet("MainWindow { background-color: rgb(187,173,160) }");
|
||||||
|
|
||||||
|
// no resizing of game window
|
||||||
|
setFixedSize(sizeHint());
|
||||||
|
|
||||||
|
connect(gameOverWindow.getResetBtn(), SIGNAL(clicked()), this, SLOT(resetGame()));
|
||||||
|
}
|
||||||
|
|
||||||
|
MainWindow::~MainWindow() {
|
||||||
|
delete scoreLabel;
|
||||||
|
delete levelLabel;
|
||||||
|
delete labelLayout;
|
||||||
|
delete scene;
|
||||||
|
delete view;
|
||||||
|
delete mainLayout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Listens to key press events from the graphical subsystem,
|
||||||
|
* and handles the events appropriately:
|
||||||
|
* - '[n]' moves hero in direction [n],
|
||||||
|
* where n = 1, 2, 3, 4, 6, 7, 8, 9 on the numeric keypad
|
||||||
|
* - '5' on the numeric keypad makes the hero wait one turn
|
||||||
|
* - 'T' teleports hero
|
||||||
|
*/
|
||||||
|
void MainWindow::keyPressEvent(QKeyEvent *e)
|
||||||
|
{
|
||||||
|
if (!gameOver) { // only process key presses while game is not over
|
||||||
|
Point pt = gameState.getHeroAsPoint();
|
||||||
|
bool actionTaken = false;
|
||||||
|
bool waiting = false;
|
||||||
|
|
||||||
|
if ((e->modifiers() == Qt::NoModifier) || (e->modifiers() == Qt::KeypadModifier)) {
|
||||||
|
switch (e->key()) {
|
||||||
|
case Qt::Key_B:
|
||||||
|
case Qt::Key_1:
|
||||||
|
actionTaken = tryMoveHeroTowards(Point{pt.x - 1, pt.y + 1});
|
||||||
|
break;
|
||||||
|
case Qt::Key_N:
|
||||||
|
case Qt::Key_2:
|
||||||
|
actionTaken = tryMoveHeroTowards(Point{pt.x, pt.y + 1});
|
||||||
|
break;
|
||||||
|
case Qt::Key_M:
|
||||||
|
case Qt::Key_3:
|
||||||
|
actionTaken = tryMoveHeroTowards(Point{pt.x + 1, pt.y + 1});
|
||||||
|
break;
|
||||||
|
case Qt::Key_H:
|
||||||
|
case Qt::Key_4:
|
||||||
|
actionTaken = tryMoveHeroTowards(Point{pt.x - 1, pt.y});
|
||||||
|
break;
|
||||||
|
case Qt::Key_K:
|
||||||
|
case Qt::Key_6:
|
||||||
|
actionTaken = tryMoveHeroTowards(Point{pt.x + 1, pt.y});
|
||||||
|
break;
|
||||||
|
case Qt::Key_Y:
|
||||||
|
case Qt::Key_7:
|
||||||
|
actionTaken = tryMoveHeroTowards(Point{pt.x - 1, pt.y - 1});
|
||||||
|
break;
|
||||||
|
case Qt::Key_U:
|
||||||
|
case Qt::Key_8:
|
||||||
|
actionTaken = tryMoveHeroTowards(Point{pt.x, pt.y - 1});
|
||||||
|
break;
|
||||||
|
case Qt::Key_I:
|
||||||
|
case Qt::Key_9:
|
||||||
|
actionTaken = tryMoveHeroTowards(Point{pt.x + 1, pt.y - 1});
|
||||||
|
break;
|
||||||
|
case Qt::Key_J:
|
||||||
|
case Qt::Key_5:
|
||||||
|
actionTaken = true;
|
||||||
|
waiting = true;
|
||||||
|
break;
|
||||||
|
case Qt::Key_T:
|
||||||
|
gameState.teleportHero();
|
||||||
|
actionTaken = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
QWidget::keyPressEvent(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actionTaken) { // process results of viable move
|
||||||
|
processMove(waiting);
|
||||||
|
}
|
||||||
|
} else { // game is over - do not process key press
|
||||||
|
QWidget::keyPressEvent(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Try to move hero to unit
|
||||||
|
*/
|
||||||
|
bool MainWindow::tryMoveHeroTowards(const Point& point) {
|
||||||
|
if (!outsideBorder(point)) {
|
||||||
|
gameState.moveHeroTowards(point);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Process results of viable move
|
||||||
|
*/
|
||||||
|
void MainWindow::processMove(bool waiting) {
|
||||||
|
gameState.moveRobots();
|
||||||
|
gameState.updateCrashes();
|
||||||
|
score += gameState.countToBeJunked() * (POINTS_PER_ROBOT +
|
||||||
|
(waiting ? WAIT_BONUS : 0));
|
||||||
|
gameState.junkTheCrashed();
|
||||||
|
gameState.draw(scene);
|
||||||
|
displayScore();
|
||||||
|
|
||||||
|
if (gameState.heroDead()) { // game over
|
||||||
|
gameOver = true;
|
||||||
|
gameOverWindow.show();
|
||||||
|
}else if(!gameState.someRobotsAlive()) { // won level
|
||||||
|
numberOfRobots = std::min(MAX_ROBOTS, numberOfRobots + ROBOTS_INC);
|
||||||
|
gameState = GameState(numberOfRobots);
|
||||||
|
gameState.draw(scene);
|
||||||
|
++level;
|
||||||
|
displayLevel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Is point outside of playing field?
|
||||||
|
*/
|
||||||
|
bool MainWindow::outsideBorder(Point const& point) const {
|
||||||
|
return point.x > MAX_X
|
||||||
|
|| point.y > MAX_Y
|
||||||
|
|| point.x < MIN_X
|
||||||
|
|| point.y < MIN_Y;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MainWindow::displayScore() const {
|
||||||
|
scoreLabel->setText(QString("SCORE: %1").arg(score));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::displayLevel() const {
|
||||||
|
levelLabel->setText(QString("LEVEL: %1").arg(level));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::resetGame() {
|
||||||
|
score = 0;
|
||||||
|
level = 1;
|
||||||
|
numberOfRobots = MIN_ROBOTS;
|
||||||
|
gameState = GameState(numberOfRobots);
|
||||||
|
gameState.draw(scene);
|
||||||
|
displayScore();
|
||||||
|
displayLevel();
|
||||||
|
gameOver = false;
|
||||||
|
gameOverWindow.hide();
|
||||||
|
}
|
58
src/mainwindow.h
Executable file
58
src/mainwindow.h
Executable file
@ -0,0 +1,58 @@
|
|||||||
|
/**
|
||||||
|
* TDDD86 Robots
|
||||||
|
* This file contains the declaration of the mainwindow class.
|
||||||
|
* See mainwindow.cpp for implementation of each member.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MAINWINDOW_H
|
||||||
|
#define MAINWINDOW_H
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
#include <QGraphicsView>
|
||||||
|
#include <QGraphicsScene>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QKeyEvent>
|
||||||
|
#include "qgameoverwindow.h"
|
||||||
|
#include "constants.h"
|
||||||
|
#include "GameState.h"
|
||||||
|
|
||||||
|
class MainWindow : public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit MainWindow(QWidget *parent = 0);
|
||||||
|
~MainWindow();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void keyPressEvent(QKeyEvent *k);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void resetGame();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QVBoxLayout* mainLayout = nullptr; // main layout
|
||||||
|
QHBoxLayout* labelLayout = nullptr; // label layout
|
||||||
|
QGraphicsView* view = nullptr; // playing field widget
|
||||||
|
QGraphicsScene* scene = nullptr; // scene for playing field
|
||||||
|
QLabel* scoreLabel = nullptr; // score widget
|
||||||
|
QLabel* levelLabel = nullptr; // level widget
|
||||||
|
QGameOverWindow gameOverWindow; // game over widget
|
||||||
|
|
||||||
|
int score = 0; // current score
|
||||||
|
int level = 1; // current level
|
||||||
|
int numberOfRobots = MIN_ROBOTS; // current no. of robots
|
||||||
|
GameState gameState = GameState(numberOfRobots); // current state of game
|
||||||
|
bool gameOver = false;
|
||||||
|
|
||||||
|
// private helpers
|
||||||
|
bool tryMoveHeroTowards(const Point &point);
|
||||||
|
void processMove(bool waiting);
|
||||||
|
bool outsideBorder(const Point &point) const;
|
||||||
|
void displayScore() const;
|
||||||
|
void displayLevel() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MAINWINDOW_H
|
42
src/qgameoverwindow.cpp
Executable file
42
src/qgameoverwindow.cpp
Executable file
@ -0,0 +1,42 @@
|
|||||||
|
/**
|
||||||
|
* TDDD86 Robots
|
||||||
|
* This file contains the implementation of the QGameOverWindow class.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "qgameoverwindow.h"
|
||||||
|
#include "qresetbutton.h"
|
||||||
|
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QLabel>
|
||||||
|
|
||||||
|
QGameOverWindow::QGameOverWindow(QWidget *parent) :
|
||||||
|
QWidget(parent) {
|
||||||
|
setStyleSheet("QGameOverWindow { background: rgb(237,224,200); }");
|
||||||
|
setFixedSize(425, 205);
|
||||||
|
QVBoxLayout *layout = new QVBoxLayout(this);
|
||||||
|
|
||||||
|
// game over label
|
||||||
|
QLabel* gameover = new QLabel("Game Over!", this);
|
||||||
|
gameover->setStyleSheet("QLabel { color: rgb(119,110,101); font: 40pt; font: bold;} ");
|
||||||
|
|
||||||
|
// reset button
|
||||||
|
reset = new QResetButton(this);
|
||||||
|
reset->setFixedHeight(50);
|
||||||
|
reset->setFixedWidth(100);
|
||||||
|
|
||||||
|
// add game over label to window
|
||||||
|
layout->insertWidget(0, gameover, 0, Qt::AlignCenter);
|
||||||
|
|
||||||
|
// add reset button to window
|
||||||
|
layout->insertWidget(1, reset, 0, Qt::AlignCenter);
|
||||||
|
}
|
||||||
|
|
||||||
|
QGameOverWindow::~QGameOverWindow() {
|
||||||
|
delete reset;
|
||||||
|
delete gameover;
|
||||||
|
delete layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
QResetButton* QGameOverWindow::getResetBtn() const {
|
||||||
|
return reset;
|
||||||
|
}
|
35
src/qgameoverwindow.h
Executable file
35
src/qgameoverwindow.h
Executable file
@ -0,0 +1,35 @@
|
|||||||
|
/**
|
||||||
|
* TDDD86 Robots
|
||||||
|
* This file contains the declaration of the QGameOverWindow class.
|
||||||
|
* See qgameoverwindow.cpp for implementation of each member.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef QGAMEOVERWINDOW_H
|
||||||
|
#define QGAMEOVERWINDOW_H
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QLabel>
|
||||||
|
#include "qresetbutton.h"
|
||||||
|
|
||||||
|
class QGameOverWindow : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit QGameOverWindow(QWidget *parent = 0);
|
||||||
|
~QGameOverWindow();
|
||||||
|
|
||||||
|
QResetButton* getResetBtn() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
QVBoxLayout *layout = nullptr;
|
||||||
|
QLabel* gameover = nullptr;
|
||||||
|
QResetButton* reset = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // QGAMEOVERWINDOW_H
|
18
src/qresetbutton.cpp
Executable file
18
src/qresetbutton.cpp
Executable file
@ -0,0 +1,18 @@
|
|||||||
|
/**
|
||||||
|
* TDDD86 Robots
|
||||||
|
* This file contains the implementation of the QResetButton class.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "qresetbutton.h"
|
||||||
|
|
||||||
|
QResetButton::QResetButton( QWidget* parent) : QLabel(parent) {
|
||||||
|
setText("Try again!");
|
||||||
|
setAlignment(Qt::AlignCenter);
|
||||||
|
setStyleSheet("QResetButton { background-color: rgb(143,122,102); border-radius: 10px; font: bold; color: white; }");
|
||||||
|
}
|
||||||
|
|
||||||
|
void QResetButton::mousePressEvent(QMouseEvent* event) {
|
||||||
|
if (event) {
|
||||||
|
emit clicked();
|
||||||
|
}
|
||||||
|
}
|
28
src/qresetbutton.h
Executable file
28
src/qresetbutton.h
Executable file
@ -0,0 +1,28 @@
|
|||||||
|
/**
|
||||||
|
* TDDD86 Robots
|
||||||
|
* This file contains the declaration of the QResetButton class.
|
||||||
|
* See qresetbutton.cpp for implementation of each member.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef QRESETBUTTON_H
|
||||||
|
#define QRESETBUTTON_H
|
||||||
|
|
||||||
|
#include <QLabel>
|
||||||
|
|
||||||
|
class QResetButton : public QLabel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
QResetButton( QWidget* parent = 0);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void clicked();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void mousePressEvent(QMouseEvent* event);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // QRESETBUTTON_H
|
21
src/robotsmain.cpp
Executable file
21
src/robotsmain.cpp
Executable file
@ -0,0 +1,21 @@
|
|||||||
|
/**
|
||||||
|
* TDDD86 Robots
|
||||||
|
* This client program contains the 'main' function to set up the overall
|
||||||
|
* program's graphical user interface.
|
||||||
|
* Your code should work properly with an unmodified version of this file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
#include "mainwindow.h"
|
||||||
|
#include "utilities.h"
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
QApplication a(argc, argv);
|
||||||
|
|
||||||
|
rand_seed(); // seed random number generator
|
||||||
|
|
||||||
|
MainWindow view; // create main window
|
||||||
|
view.show(); // display main window
|
||||||
|
|
||||||
|
return a.exec(); // start Qt event loop
|
||||||
|
}
|
18
src/utilities.cpp
Executable file
18
src/utilities.cpp
Executable file
@ -0,0 +1,18 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (C) David Wolfe, 1999. All rights reserved.
|
||||||
|
* Ported to Qt and adapted for TDDD86, 2015.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "utilities.h"
|
||||||
|
#include "constants.h"
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
|
void rand_seed() {
|
||||||
|
int seed = static_cast<int>(time(0));
|
||||||
|
srand(seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
int rand_int(int a, int b) {
|
||||||
|
return a + rand() % (b - a + 1);
|
||||||
|
}
|
27
src/utilities.h
Executable file
27
src/utilities.h
Executable file
@ -0,0 +1,27 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (C) David Wolfe, 1999. All rights reserved.
|
||||||
|
* Ported to Qt and adapted for TDDD86, 2015.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef UTILITIES_H
|
||||||
|
#define UTILITIES_H
|
||||||
|
|
||||||
|
struct Point {
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the seed of the random number generator.
|
||||||
|
*/
|
||||||
|
void rand_seed();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a random integer in a range.
|
||||||
|
* @param a the bottom of the range
|
||||||
|
* @param b the top of the range
|
||||||
|
* &return a random number x having a <= x and x <= b
|
||||||
|
*/
|
||||||
|
int rand_int(int a, int b);
|
||||||
|
|
||||||
|
#endif // UTILITIES_H
|
Loading…
x
Reference in New Issue
Block a user