spells pt1
This commit is contained in:
parent
abd3eb9a9b
commit
2686764cb3
@ -31,4 +31,10 @@ Actor::~Actor() {
|
||||
if (ai) delete ai;
|
||||
if (pickable) delete pickable;
|
||||
if (container) delete container;
|
||||
}
|
||||
|
||||
float Actor::getDistance(int cx, int cy) const {
|
||||
int dx = x - cx;
|
||||
int dy = y - cy;
|
||||
return sqrtf(dx * dx + dy * dy);
|
||||
}
|
2
Actor.h
2
Actor.h
@ -21,7 +21,7 @@ public:
|
||||
Ai* ai;
|
||||
Pickable* pickable; // something that can be picked and used
|
||||
Container* container; // something that can contain actors
|
||||
|
||||
float getDistance(int cx, int cy) const;
|
||||
Actor(int x, int y, std::string_view ch, std::string name, const TCOD_ColorRGB& col);
|
||||
~Actor();
|
||||
void render(TCOD_Console& cons) const;
|
||||
|
@ -14,7 +14,7 @@ project ("ADG5")
|
||||
find_package(libtcod CONFIG REQUIRED)
|
||||
|
||||
# Add source to this project's executable.
|
||||
add_executable (ADG5 "ADG5.cpp" "ADG5.h" "Actor.cpp" "Actor.h" "Map.h" "Map.cpp" "Engine.h" "Engine.cpp" "Destructible.h" "Destructible.cpp" "Attacker.h" "Attacker.cpp" "Ai.h" "Ai.cpp" "Gui.h" "Gui.cpp" "Container.h" "Container.cpp" "Pickable.h" "Pickable.cpp" "Healer.h" "Healer.cpp")
|
||||
add_executable (ADG5 "ADG5.cpp" "ADG5.h" "Actor.cpp" "Actor.h" "Map.h" "Map.cpp" "Engine.h" "Engine.cpp" "Destructible.h" "Destructible.cpp" "Attacker.h" "Attacker.cpp" "Ai.h" "Ai.cpp" "Gui.h" "Gui.cpp" "Container.h" "Container.cpp" "Pickable.h" "Pickable.cpp" "Healer.h" "Healer.cpp" "Lightningbolt.h" "Lightningbolt.cpp" "Fireball.h" "Fireball.cpp")
|
||||
|
||||
target_link_libraries(ADG5
|
||||
PRIVATE
|
||||
|
76
Engine.cpp
76
Engine.cpp
@ -22,6 +22,8 @@ Engine::Engine(int screenWidth, int screenHeight, tcod::Context *context, tcod::
|
||||
gameStatus = STARTUP;
|
||||
mouse.cx = 0;
|
||||
mouse.cy = 0;
|
||||
mouse.rbutton_pressed = false;
|
||||
mouse.lbutton_pressed = false;
|
||||
}
|
||||
|
||||
void Engine::init() {
|
||||
@ -62,7 +64,7 @@ bool Engine::update() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void Engine::render() {
|
||||
void Engine::render(bool present) {
|
||||
console->clear();
|
||||
// draw the map
|
||||
map->render(*console);
|
||||
@ -77,10 +79,80 @@ void Engine::render() {
|
||||
}
|
||||
player->render(*console);
|
||||
gui->render();
|
||||
context->present(*console);
|
||||
if (present)
|
||||
context->present(*console);
|
||||
}
|
||||
|
||||
void Engine::sendToBack(Actor* actor) {
|
||||
actors.remove(actor);
|
||||
actors.insertBefore(actor, 0);
|
||||
}
|
||||
|
||||
Actor* Engine::getClosestMonster(int x, int y, float range) const {
|
||||
Actor* closest = NULL;
|
||||
float bestDistance = 1E6f;
|
||||
for (Actor** iterator = actors.begin();
|
||||
iterator != actors.end(); iterator++) {
|
||||
Actor* actor = *iterator;
|
||||
if (actor != player && actor->destructible
|
||||
&& !actor->destructible->isDead()) {
|
||||
float distance = actor->getDistance(x, y);
|
||||
if (distance < bestDistance && (distance <= range || range == 0.0f)) {
|
||||
bestDistance = distance;
|
||||
closest = actor;
|
||||
}
|
||||
}
|
||||
}
|
||||
return closest;
|
||||
}
|
||||
|
||||
bool Engine::pickATile(int* x, int* y, float maxRange) {
|
||||
while (context->get_sdl_window() != nullptr) {
|
||||
render(false);
|
||||
|
||||
// highlight the possible range
|
||||
for (int cx = 0; cx < map->width; cx++) {
|
||||
for (int cy = 0; cy < map->height; cy++) {
|
||||
if (map->isInFov(cx, cy)
|
||||
&& (maxRange == 0 || player->getDistance(cx, cy) <= maxRange)) {
|
||||
TCOD_ColorRGBA col = console->at(cx, cy).bg;
|
||||
|
||||
col.r = col.r * 1.2f;
|
||||
col.g = col.g * 1.2f;
|
||||
col.b = col.b * 1.2f;
|
||||
|
||||
console->at(cx, cy).bg = col;
|
||||
}
|
||||
}
|
||||
}
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event)) {
|
||||
engine->context->convert_event_coordinates(event);
|
||||
switch (event.type) {
|
||||
case SDL_EVENT_MOUSE_MOTION:
|
||||
engine->mouse.cx = event.motion.x;
|
||||
engine->mouse.cy = event.motion.y;
|
||||
break;
|
||||
case SDL_EVENT_MOUSE_BUTTON_DOWN:
|
||||
engine->mouse.lbutton_pressed = event.button.button == SDL_BUTTON_LEFT;
|
||||
engine->mouse.rbutton_pressed = event.button.button == SDL_BUTTON_RIGHT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (map->isInFov(mouse.cx, mouse.cy)
|
||||
&& (maxRange == 0 || player->getDistance(mouse.cx, mouse.cy) <= maxRange)) {
|
||||
console->at(mouse.cx, mouse.cy).bg = TCOD_ColorRGBA(100, 100, 100, 255);
|
||||
if (mouse.lbutton_pressed) {
|
||||
*x = mouse.cx;
|
||||
*y = mouse.cy;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (mouse.rbutton_pressed) {
|
||||
return false;
|
||||
}
|
||||
context->present(*console);
|
||||
}
|
||||
return false;
|
||||
}
|
4
Engine.h
4
Engine.h
@ -30,8 +30,10 @@ public:
|
||||
void init();
|
||||
~Engine();
|
||||
bool update();
|
||||
void render();
|
||||
void render(bool present = true);
|
||||
void sendToBack(Actor* actor);
|
||||
Actor* getClosestMonster(int x, int y, float range) const;
|
||||
bool pickATile(int* x, int* y, float maxRange = 0.0f);
|
||||
private:
|
||||
bool computeFov;
|
||||
};
|
||||
|
30
Fireball.cpp
Normal file
30
Fireball.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
#include "libtcod.hpp"
|
||||
#include "Fireball.h"
|
||||
#include "Engine.h"
|
||||
#include "Gui.h"
|
||||
#include "Destructible.h"
|
||||
#include "Actor.h"
|
||||
|
||||
Fireball::Fireball(float range, float damage)
|
||||
: LightningBolt(range, damage) {
|
||||
}
|
||||
|
||||
bool Fireball::use(Actor* owner, Actor* wearer) {
|
||||
engine->gui->message(TCOD_ColorRGB(0, 255, 255), "Left-click a target tile for the fireball,\nor right-click to cancel.");
|
||||
int x, y;
|
||||
if (!engine->pickATile(&x, &y)) {
|
||||
return false;
|
||||
}
|
||||
engine->gui->message(TCOD_ColorRGB(255, 255, 100), "The fireball explodes, burning everything within %g tiles!", range);
|
||||
for (Actor** iterator = engine->actors.begin();
|
||||
iterator != engine->actors.end(); iterator++) {
|
||||
Actor* actor = *iterator;
|
||||
if (actor->destructible && !actor->destructible->isDead()
|
||||
&& actor->getDistance(x, y) <= range) {
|
||||
engine->gui->message(TCOD_ColorRGB(255, 255, 100), "The %s gets burned for %g hit points.",
|
||||
actor->name.c_str(), damage);
|
||||
actor->destructible->takeDamage(actor, damage);
|
||||
}
|
||||
}
|
||||
return Pickable::use(owner, wearer);
|
||||
}
|
10
Fireball.h
Normal file
10
Fireball.h
Normal file
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "Lightningbolt.h"
|
||||
|
||||
|
||||
class Fireball : public LightningBolt {
|
||||
public:
|
||||
Fireball(float range, float damage);
|
||||
bool use(Actor* owner, Actor* wearer);
|
||||
};
|
24
Lightningbolt.cpp
Normal file
24
Lightningbolt.cpp
Normal file
@ -0,0 +1,24 @@
|
||||
#include "Lightningbolt.h"
|
||||
#include "Engine.h"
|
||||
#include "Actor.h"
|
||||
#include "Gui.h"
|
||||
#include "Destructible.h"
|
||||
|
||||
LightningBolt::LightningBolt(float range, float damage)
|
||||
: range(range), damage(damage) {
|
||||
}
|
||||
|
||||
bool LightningBolt::use(Actor* owner, Actor* wearer) {
|
||||
Actor* closestMonster = engine->getClosestMonster(wearer->x, wearer->y, range);
|
||||
if (!closestMonster) {
|
||||
engine->gui->message(TCOD_ColorRGB(200,200,200), "No enemy is close enough to strike.");
|
||||
return false;
|
||||
}
|
||||
// hit closest monster for <damage> hit points
|
||||
engine->gui->message(TCOD_ColorRGB(100, 255, 100),
|
||||
"A lighting bolt strikes the %s with a loud crack of thunder!\n"
|
||||
"The damage is %g hit points.",
|
||||
closestMonster->name.c_str(), damage);
|
||||
closestMonster->destructible->takeDamage(closestMonster, damage);
|
||||
return Pickable::use(owner, wearer);
|
||||
}
|
12
Lightningbolt.h
Normal file
12
Lightningbolt.h
Normal file
@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include "Pickable.h"
|
||||
|
||||
class Actor;
|
||||
|
||||
class LightningBolt : public Pickable {
|
||||
public:
|
||||
float range, damage;
|
||||
LightningBolt(float range, float damage);
|
||||
bool use(Actor* owner, Actor* wearer);
|
||||
};
|
34
Map.cpp
34
Map.cpp
@ -6,6 +6,8 @@
|
||||
#include "Attacker.h"
|
||||
#include "Ai.h"
|
||||
#include "Healer.h"
|
||||
#include "Lightningbolt.h"
|
||||
#include "Fireball.h"
|
||||
|
||||
static const int ROOM_MAX_SIZE = 12;
|
||||
static const int ROOM_MIN_SIZE = 6;
|
||||
@ -190,9 +192,31 @@ void Map::addMonster(int x, int y) {
|
||||
}
|
||||
|
||||
void Map::addItem(int x, int y) {
|
||||
Actor* healthPotion = new Actor(x, y, "!", "health potion",
|
||||
TCOD_ColorRGB(128, 0, 128));
|
||||
healthPotion->blocks = false;
|
||||
healthPotion->pickable = new Healer(4);
|
||||
engine->actors.push(healthPotion);
|
||||
TCODRandom* rng = TCODRandom::getInstance();
|
||||
int dice = rng->getInt(0, 100);
|
||||
if (dice < 70) {
|
||||
// create a health potion
|
||||
Actor* healthPotion = new Actor(x, y, "!", "health potion",
|
||||
TCOD_ColorRGB(128, 0, 128));
|
||||
healthPotion->blocks = false;
|
||||
healthPotion->pickable = new Healer(4);
|
||||
engine->actors.push(healthPotion);
|
||||
}
|
||||
else if (dice < 70 + 10) {
|
||||
// create a scroll of lightning bolt
|
||||
Actor* scrollOfLightningBolt = new Actor(x, y, "#", "scroll of lightning bolt",
|
||||
TCOD_ColorRGB(255, 100, 100));
|
||||
scrollOfLightningBolt->blocks = false;
|
||||
scrollOfLightningBolt->pickable = new LightningBolt(5, 20);
|
||||
engine->actors.push(scrollOfLightningBolt);
|
||||
}
|
||||
|
||||
else if (dice < 70 + 10 + 10) {
|
||||
// create a scroll of fireball
|
||||
Actor* scrollOfFireball = new Actor(x, y, "#", "scroll of fireball",
|
||||
TCOD_ColorRGB(255, 100, 100));
|
||||
scrollOfFireball->blocks = false;
|
||||
scrollOfFireball->pickable = new Fireball(3, 12);
|
||||
engine->actors.push(scrollOfFireball);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user