My floodfilling algorithm is nearly finished, but there is a small error somewhere, I've spent about 3 hours debugging, but i can't seem to find it!
note:
When reading in I use numbers from 0 to 15 to define the walls
1 = top
2 = right
4 = bottom
8 = left
(so 13 would mean that the top/bottom/left walls are there)
My Program:
It reads in number of fields to calculate the biggest room from (so everything below here is a cycle that gets repeated for the number of fields).
Then it gets the room's dimensions
Now in the class field, it creates an array of objects (Cell) which store the walls around (left right down up), and a value below 16
Now here is where I think the problem comes, reading in values through std::cin
and then when everything is read in, it scans for empty (0), and then creates a room, and checks for availeble spaces around it (using the wall-check)
and at the end it returns the max value, and we are done.
The input I use:
1
2 2
13 3
15 14
so what happens is is that somewhere, in or the wall-check, or the creation of a object Cell something goes wrong (I think)
Here is my script, and sorry to have to ask something silly like this!
Thanks in advance
// een simpele floodfill
#include <stdlib.h>
#include <iostream>
#include <bitset>
class Cell {
private:
int kamer, value;
bool left, right, up, down;
public:
// constructor
Cell::Cell() {};
// functions
bool CanLeft() { return left ; }
bool CanRight() { return right; }
bool CanDown() { return down ; }
bool CanUp() { return up ; }
int GetRoom() { return kamer; }
void SetRoom(int x) { kamer = x ; }
void SetValue(int x, int room=0) { value = x;
kamer = room;
std::bitset<sizeof(int)> bits(value);
if (bits[3]) left = true;
else left = false;
if (bits[2]) down = true;
else down = false;
if (bits[1]) right = true;
else right = false;
if (bits[0]) up = true;
else up = false;
}
};
class Field {
private:
int Biggest_Chamber;
int Y;
int X;
int temp;
Cell playfield[][1];
public:
// constructor
Field::Field(int SizeY, int SizeX) {
Y = SizeY;
X = SizeX;
Cell playfield[SizeY-1][SizeX-1];
}
// Create a 2d array and fill it
void Get_input() {
for (int Yas = 0; Yas < Y; Yas++){
for (int Xas = 0; Xas < X; Xas++){
std::cin >> temp;
playfield[Yas][Xas].SetValue(temp);
}
}
};
void Start() { Mark(0,0,1); }
void Mark(int y, int x, int nr) {
std::cout << nr;
temp = nr;
playfield[y][x].SetRoom(nr);
if (playfield[y][x].CanLeft()) {
if (playfield[y][x-1].GetRoom() != 0) {
Mark(y, x-1, nr);
std::cout << nr;
system("pause");}}
if (playfield[y][x].CanDown()) {
if (playfield[y+1][x].GetRoom() != 0) {
Mark(y+1, x, nr);
std::cout << nr;
system("pause");}}
if (playfield[y][x].CanRight()) {
if (playfield[y][x+1].GetRoom() != 0) {
Mark(y, x+1, nr);
std::cout << nr;
system("pause");}}
if (playfield[y][x].CanUp()) {
if (playfield[y-1][x].GetRoom() != 0) {
Mark(y-1, x, nr);
std::cout << nr;
system("pause");}}
for (int vertical = 0; vertical < Y; vertical++) {
for (int horizontal = 0; horizontal < X; horizontal++) {
if (playfield[vertical][horizontal].GetRoom() == 0) Mark(vertical, horizontal, nr+1);
}
}
}
int MaxValue() {
int counter[temp];
int max = 0;
for (int y = 0; y < Y; y++) {
for (int x = 0; x < X; x++) {
counter[playfield[y][x].GetRoom()]++;
}
}
for (int i = 0; i < temp; i++)
{
if (counter[i] > max)
max = counter[i];
}
return max;
}
};
int main() {
using namespace std;
int NrKamers;
int sizeY;
int sizeX;
std::cin >> NrKamers;
for (int i = 0; i < NrKamers; i++){
std::cin >> sizeY >> sizeX;
Field floodfield(sizeY, sizeX);
floodfield.Get_input();
floodfield.Start();
std::cout << floodfield.MaxValue() << std::endl;
}
return 0;
}
I have not had much time to deal with the code, but my first impression is that you are not marking (or rather not using the mark) each visited position in the array, so that you move in one direction, and while processing that other position you return back to the original square. Consider that the sequence of tests where: left, right, up, down; and that you start in the top-left corner:
You cannot move left, but you can move right. At that second recursion level you can move left and go back to square one. Then you cannot move left, but you can move right, so you go back to square two, from which you move to square one... infinitedly.
Before you move to the next square you have to mark your square as visited, and also check that the square you intend to move to has not been visited in the current run.
The segmentation fault is the result of infinite recursion, after you exhaust the stack.
1-11-2017: NEW-VERSION; SUCCESFULLY TESTED WITH TWO BITMAPS.
I propose my C version of the Flood-Fill algorithm, which doesn't uses recursive calls, but only a queue of the offsets of the new points, it works on the window: WinnOffs-(WinDimX,WinDimY) of the double-buffer: *VBuffer (copy of the screen or image) and, optionally, it write a mask of the flood-fill's result (*ExtraVBuff).
ExtraVBuff must be filled it with 0 before the call (if you don't need a mask you may set ExtraVBuff= NULL); using it after call you can do gradient floodfill or other painting effects. NewFloodFill works with 32 Bit per Pixel and it is a C function. I've reinvented this algorithm in 1991 (I wrote his in Pascal), but now it works in C with 32 Bit per Pixel; also not uses any functions calls, does only a division after each "pop" from queue, and never overflows the queue, that, if it is sized in the right way (about 1/4 of the pixels of the image), it allows always to fill correctly any area; I show before the c-function (FFILL.C), after the test program (TEST.C):
#define IMAGE_WIDTH 1024
#define IMAGE_HEIGHT 768
#define IMAGE_SIZE IMAGE_WIDTH*IMAGE_HEIGHT
#define QUEUE_MAX IMAGE_SIZE/4
typedef int T_Queue[QUEUE_MAX];
typedef int T_Image[IMAGE_SIZE];
void NewFloodFill(int X,
int Y,
int Color,
int BuffDimX,
int WinOffS,
int WinDimX,
int WinDimY,
T_Image VBuffer,
T_Image ExtraVBuff,
T_Queue MyQueue)
/* Replaces all pixels adjacent to the first pixel and equal to this; */
/* if ExtraVBuff == NULL writes to *VBuffer (eg BUFFER of 786432 Pixel),*/
/* otherwise prepare a mask by writing on *ExtraVBuff (such BUFFER must */
/* always have the same size as *VBuffer (it must be initialized to 0)).*/
/* X,Y: Point coordinates' of origin of the flood-fill. */
/* WinOffS: Writing start offset on *VBuffer and *ExtraVBuff. */
/* BuffDimX: Width, in number of Pixel (int), of each buffer. */
/* WinDimX: Width, in number of Pixel (int), of the window. */
/* Color: New color that replace all_Pixel == origin's_point. */
/* WinDimY: Height, in number of Pixel (int), of the window. */
/* VBuffer: Pointer to the primary buffer. */
/* ExtraVBuff: Pointer to the mask buffer (can be = NULL). */
/* MyQueue: Pointer to the queue, containing the new-points' offsets*/
{
int VBuffCurrOffs=WinOffS+X+Y*BuffDimX;
int PixelIn=VBuffer[VBuffCurrOffs];
int QueuePnt=0;
int *TempAddr=((ExtraVBuff) ? ExtraVBuff : VBuffer);
int TempOffs1;
int TempX1;
int TempX2;
char FLAG;
if (0<=X && X<WinDimX && 0<=Y && Y<WinDimY) do
{
/* Fill to left the current line */
TempX2=X;
while (X>=0 && PixelIn==VBuffer[VBuffCurrOffs])
{
TempAddr[VBuffCurrOffs--]=Color;
--X;
}
TempOffs1=VBuffCurrOffs+1;
TempX1=X+1;
/* Fill to right the current line */
VBuffCurrOffs+=TempX2-X;
X=TempX2;
while (X+1<WinDimX && PixelIn==VBuffer[VBuffCurrOffs+1])
{
++X;
TempAddr[++VBuffCurrOffs]=Color;
}
TempX2=X;
/* Backward scan of the previous line; puts new points offset in Queue[] */
if (Y>0)
{
FLAG=1;
VBuffCurrOffs-=BuffDimX;
while (X-->=TempX1)
{
if (PixelIn!=VBuffer[VBuffCurrOffs] ||
ExtraVBuff && Color==ExtraVBuff[VBuffCurrOffs])
FLAG=1;
else
if (FLAG)
{
FLAG=0;
if (QueuePnt<QUEUE_MAX)
MyQueue[QueuePnt++]=VBuffCurrOffs;
}
--VBuffCurrOffs;
}
}
/* Forward scan of the next line; puts new points offset in Queue[] */
if (Y<WinDimY-1)
{
FLAG=1;
VBuffCurrOffs=TempOffs1+BuffDimX;
X=TempX1;
while (X++<=TempX2)
{
if (PixelIn!=VBuffer[VBuffCurrOffs] ||
ExtraVBuff && Color==ExtraVBuff[VBuffCurrOffs])
FLAG=1;
else
if (FLAG)
{
FLAG=0;
if (QueuePnt<QUEUE_MAX)
MyQueue[QueuePnt++]=VBuffCurrOffs;
}
++VBuffCurrOffs;
}
}
/* Gets a new point offset from Queue[] */
if (--QueuePnt>=0)
{
VBuffCurrOffs=MyQueue[QueuePnt];
TempOffs1=VBuffCurrOffs-WinOffS;
X=TempOffs1%BuffDimX;
Y=TempOffs1/BuffDimX;
}
/* Repeat the main cycle until the Queue[] is not empty */
} while (QueuePnt>=0);
}
Here there is the test program:
#include <stdio.h>
#include <malloc.h>
#include "ffill.c"
#define RED_COL 0xFFFF0000
#define WIN_LEFT 52
#define WIN_TOP 48
#define WIN_WIDTH 920
#define WIN_HEIGHT 672
#define START_LEFT 0
#define START_TOP 671
#define BMP_HEADER_SIZE 54
typedef char T_Image_Header[BMP_HEADER_SIZE];
void main(void)
{
T_Image_Header bmpheader;
T_Image *image;
T_Image *mask;
T_Queue *MyQueue;
FILE *stream;
char *filename1="ffill1.bmp";
char *filename2="ffill2.bmp";
char *filename3="ffill3.bmp";
int bwritten;
int bread;
image=malloc(sizeof(*image));
mask=malloc(sizeof(*mask));
MyQueue=malloc(sizeof(*MyQueue));
stream=fopen(filename1,"rb");
bread=fread(&bmpheader, 1, BMP_HEADER_SIZE, stream);
bread=fread((char *)image, 1, IMAGE_SIZE<<2, stream);
fclose(stream);
memset(mask,0,IMAGE_SIZE<<2);
NewFloodFill(START_LEFT,
START_TOP,
RED_COL,
IMAGE_WIDTH,
IMAGE_WIDTH*WIN_TOP+WIN_LEFT,
WIN_WIDTH,
WIN_HEIGHT,
*image,
NULL,
*MyQueue);
stream=fopen(filename2,"wb+");
bwritten=fwrite(&bmpheader, 1, BMP_HEADER_SIZE, stream);
bwritten=fwrite((char *)image, 1, IMAGE_SIZE<<2, stream);
fclose(stream);
stream=fopen(filename3,"wb+");
bwritten=fwrite(&bmpheader, 1, BMP_HEADER_SIZE, stream);
bwritten=fwrite((char *)mask, 1, IMAGE_SIZE<<2, stream);
fclose(stream);
free(MyQueue);
free(mask);
free(image);
}
I've used, for the input of the test program shown, the follow Windows uncompressed .BMP image (ffill1.bmp):
Filled, by the test program shown, as follows (ffill2.bmp):
Using "mask" instead of NULL, the output bitmap is (ffill3.bmp):
Related
I have a school project where we have to create a game on C++. We are divided into groups and I had to create the pathfinding for it. The program compiles (although it is very slow) and my algorithm does not work. It does not always find the shortest path.
The game is the following: You have a labyrinth, a player and three enemies. The task is to make the enemies find their path to the player and they can move only one "character" every time the player moves.
#include "MapGeneration.cpp"
#include <iostream>
#include <string>
#include <stdlib.h>
#include "EnemyClass.cpp" //use the enemy stuff to get the entity stuff
//in EntityClass see if the xPos and yPos are changing
using namespace std;
/* Variables */
int row; // rows
int col; // columns
const int enemnumb = 3;
const int playnumb = 1;
int playcount = 1; // Counting how much players are left
int enemcount = 3; // Counting how much enemies are left
int enemcordr[enemnumb]; // Enemy row number
int enemcordc[enemnumb]; // Enemy column number
int playcordr[playnumb]; // Player row number
int playcordc[playnumb]; // Player column number
/* Find enemies */
int findAllEnem(){
bool found = false;
while(!found){ // If all enemies are found while loop stops
for(row=0;row<MapRowSize;row++){ // Searches in rows
for(col=0;col<MapColumnSize;col++){ // Searches in columns
if(arrCurrentMap[row][col]=='e'){ // If it finds the letter 'e'
enemcordr[enemcount]=row; // Save the row number
enemcordc[enemcount]=col; // Save the column number
enemcount--; // Substracts 1 from the enemy count in order to show how much are left
}
if(enemcount==0){ // If there are no left enemies
found=true; // All enemies will be found and will stop the while loop
}
}
}
}
}
/* Find players */
int findPlayer(){
bool found = false;
while(!found){ // If player is found
for(row=0;row<MapRowSize;row++){ // Searches in rows
for(col=0;col<MapColumnSize;col++){ // Searches in columns
if(arrCurrentMap[row][col]=='p'){ // If it finds the letter 'e'
playcordr[playcount]=row; // Save the row number
playcordc[playcount]=col; // Save the column number
playcount--; // Substracts 1 from the enemy count in order to show how much are left
}
if(playcount==0){ // If there are no left enemies
found=true; // All enemies will be found and will stop the while loop
}
}
}
}
}
int enemMovement() {
srand(time(NULL));
bool makeMove = false; // to check if the enemy has already made a move
bool legit = false;
const int possible = 1500;
int possmov = 1;
int min[possible]; // minimum distance
int countMove[possible][enemnumb]; // counts how many moves have been made with road
int moveR[possible][enemnumb]; // gets virtual row without moving the enemy
int moveC[possible][enemnumb]; // gets virtual column without moving the enemy
int found[possible][enemnumb]; // if enemy found the player
for (playcount = playnumb; playcount > 0; playcount--) { // for every player
for (enemcount = enemnumb; enemcount > 0; enemcount--) { // the three enemies
for (possmov = 0; possmov < possible; possmov++) { // possible directions
moveR[possmov][enemcount] = enemcordr[enemcount];
moveC[possmov][enemcount] = enemcordc[enemcount];
while (legit != true) {
int previous;
int nRand = rand()%(4-0)+1; //4 possible directions
if (nRand == 1) { //move right
if (arrCurrentMap[moveR[possmov][enemcount]][moveC[possmov][enemcount] + 1] != '#') {
if (arrCurrentMap[moveR[possmov][enemcount]][moveC[possmov][enemcount] + 1] == 'p') {
found[possmov][enemcount]=countMove[possmov][enemcount];
legit=true;
}
moveC[possmov][enemcount]++;
countMove[possmov][enemcount]++;
}
}
if (nRand == 2) // move left
{
if (arrCurrentMap[moveR[possmov][enemcount]][moveC[possmov][enemcount] - 1] != '#') {
if (arrCurrentMap[moveR[possmov][enemcount]][moveC[possmov][enemcount] - 1] == 'p') {
found[possmov][enemcount]=countMove[possmov][enemcount];
legit=true;
}
moveC[possmov][enemcount]--;
countMove[possmov][enemcount]++;
}
}
if (nRand == 3) // move up
{
if (arrCurrentMap[moveR[possmov][enemcount] - 1][moveC[possmov][enemcount]] != '#') {
if (arrCurrentMap[moveR[possmov][enemcount] - 1][moveC[possmov][enemcount]]== 'p') {
found[possmov][enemcount]=countMove[possmov][enemcount];
legit=true;
}
moveR[possmov][enemcount]--;
countMove[possmov][enemcount]++;
}
}
if (nRand == 4) // move down
{
if (arrCurrentMap[moveR[possmov][enemcount] + 1][moveC[possmov][enemcount]] != '#') {
if (arrCurrentMap[moveR[possmov][enemcount] + 1][moveC[possmov][enemcount]]== 'p') {
found[possmov][enemcount]=countMove[possmov][enemcount];
legit=true;
}
moveR[possmov][enemcount]++;
countMove[possmov][enemcount]++;
}
}
}
legit=false; // returns the value of legit to false for next move road
}
min[enemcount]=possible;
for(int i=0;i<=possible;i++){ // finds the shortest path
if(found[i][enemcount]<min[enemcount] && found[i][enemcount] != 0){
min[enemcount]=found[i][enemcount];
}
}
}
}
}
/* Main function */
int main (){
GenerateLoadingMap(1); // Generate map
findPlayer(); // Finds players
findAllEnem(); // Find enemies
enemMovement(); // enemy movement
return 0;
}
This is the code I wrote. Sometimes it finds the shortest path but not always. Also I would like for an advice on how to store the coordinates after every move.
I'm having some trouble writing a circular buffer in C++. Here is my code base at the moment:
circ_buf.h:
#ifndef __CIRC_BUF_H__
#define __CIRC_BUF_H__
#define MAX_DATA (25) // Arbitrary size limit
// The Circular Buffer itself
struct circ_buf {
int s; // Index of oldest reading
int e; // Index of most recent reading
int data[MAX_DATA]; // The data
};
/*** Function Declarations ***/
void empty(circ_buf*);
bool is_empty(circ_buf*);
bool is_full(circ_buf*);
void read(circ_buf*, int);
int overwrite(circ_buf*);
#endif // __CIRC_BUF_H__
circ_buf.cpp:
#include "circ_buf.h"
/*** Function Definitions ***/
// Empty the buffer
void empty(circ_buf* cb) {
cb->s = 0; cb->e = 0;
}
// Is the buffer empty?
bool is_empty(circ_buf* cb) {
// By common convention, if the start index is equal to the end
// index, our buffer is considered empty.
return cb->s == cb->e;
}
// Is the buffer full?
bool is_full(circ_buf* cb) {
// By common convention, if the start index is one greater than
// the end index, our buffer is considered full.
// REMEMBER: we still need to account for wrapping around!
return cb->s == ((cb->e + 1) % MAX_DATA);
}
// Read data into the buffer
void read(circ_buf* cb, int k) {
int i = cb->e;
cb->data[i] = k;
cb->e = (i + 1) % MAX_DATA;
}
// Overwrite data in the buffer
int overwrite(circ_buf* cb) {
int i = cb->s;
int k = cb->data[i];
cb->s = (i + 1) % MAX_DATA;
}
circ_buf_test.cpp:
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
#include "circ_buf.h"
int main(int argc, char** argv) {
// Our data source
std::string file = "million_numbers.txt";
std::fstream in(file, std::ios_base::in);
// The buffer
circ_buf buffer = { .s = 0, .e = 0, .data = {} };
for (int i = 0; i < MAX_DATA; ++i) {
int k = 0; in >> k; // Get next int from in
read(&buffer, k);
}
for (int i = 0; i < MAX_DATA; ++i)
std::cout << overwrite(&buffer) << std::endl;
}
The main issue I'm having is getting the buffer to write integers to its array. When I compile and run the main program (circ_buf_test), it just prints the same number 25 times, instead of what I expect it to print (the numbers 1 through 25 - "million_numbers.txt" is literally just the numbers 1 through 1000000). The number is 2292656, in case this may be important.
Does anyone have an idea about what might be going wrong here?
Your function overwrite(circ_buf* cb) returns nothing (there are no return in it's body). So the code for printing of values can print anything (see "undefined behavior"):
for (int i = 0; i < MAX_DATA; ++i)
std::cout << overwrite(&buffer) << std::endl;
I expect you can find the reason of this "main issue" in the compilation log (see lines started with "Warning"). You can fix it this way:
int overwrite(circ_buf* cb) {
int i = cb->s;
int k = cb->data[i];
cb->s = (i + 1) % MAX_DATA;
return k;
}
I am using tile mapping and have my map class in place to draw the map by using an array of sprites. i have it to set the position of the sprite and then create a bounding box array around it and then draw the sprite.
i then have a collision class which gets the player bounding box and compares it with each bounding box for the sprite. i have an array called platformboundingBox. this stores each bounding box of each sprite in the array. however when i compare the values it seems that the platform bounding box has no values in any of the locations yet the i have checked that the values of each sprite go into the bounding box array.
here is my map class. see the drawmap and collision functions to take a look. if anyone can help i would really appreciate it.
#include "Map.h"
#include "Block.h"
#include <sstream>
using namespace std;
Map::Map()
{
//map ctor;
}
Map::~Map()
{
// map dtor
}
void Map::Initialise(const char *filename)
{
if(!BlockImage.LoadFromFile("Images/block.png"))
cout<<endl<<"failed to load block image"<<endl;
if(!GemImage.LoadFromFile("Images/Gem.png"))
cout<<endl<<"failed to load Gem Image"<<endl;
if(!leftBlockImage.LoadFromFile("Images/blockLeft.png"))
cout<<endl<<"failed to load left block Image"<<endl;
if(!rightBlockImage.LoadFromFile("Images/blockRight.png"))
cout<<endl<<"failed to load right block Image"<<endl;
std::ifstream openfile(filename);
std::vector <int> tempvector;
std::string line;
while(std::getline(openfile, line))
{
for(int i =0; i < line.length(); i++)
{
if(line[i] != ' ') // if the value is not a space
{
char value = line[i];
tempvector.push_back(value - '0');
}
}
mapVector.push_back(tempvector); // push back the value of the temp vector into the map vector
tempvector.clear(); // clear the temp vector readt for the next value
}
}
void Map::DrawMap(sf::RenderWindow &Window)
{
Player playermap;
for(i = 0; i < mapVector.size(); i++)
{
for(j = 0; j < mapVector[i].size(); j++)
{
if(mapVector[i][j] == 1)
{
sprite[j].SetImage(BlockImage);
sprite[j].SetPosition(j * BLOCKSIZE, i * BLOCKSIZE);
platformBoundingBox[j].Bottom = sprite[j].GetPosition().y;
platformBoundingBox[j].Left = sprite[j].GetPosition().x - 5;
platformBoundingBox[j].Right = sprite[j].GetPosition().x;
Window.Draw(sprite[j]);
}
else if(mapVector[i][j] == 2)
{
sprite[j].SetImage(GemImage);
sprite[j].SetPosition(j * BLOCKSIZE, i * BLOCKSIZE);
platformBoundingBox[j].Top = sprite[j].GetPosition().y - 5;
platformBoundingBox[j].Bottom = sprite[j].GetPosition().y;
platformBoundingBox[j].Left = sprite[j].GetPosition().x - 5;
platformBoundingBox[j].Right = sprite[j].GetPosition().x;
Window.Draw(sprite[j]);
}
else if(mapVector[i][j] == 3)
{
sprite[j].SetImage(leftBlockImage);
sprite[j].SetPosition(j * BLOCKSIZE, i * BLOCKSIZE);
platformBoundingBox[j].Top = sprite[i].GetPosition().y - 5;
platformBoundingBox[j].Bottom = sprite[i].GetPosition().y;
platformBoundingBox[j].Left = sprite[i].GetPosition().x - 5;
platformBoundingBox[j].Right = sprite[i].GetPosition().x;
Window.Draw(sprite[j]);
}
else if(mapVector[i][j] == 4)
{
sprite[j].SetImage(rightBlockImage);
sprite[j].SetPosition(j * BLOCKSIZE, i * BLOCKSIZE);
platformBoundingBox[j].Top = sprite[i].GetPosition().y - 5;
platformBoundingBox[j].Bottom = sprite[i].GetPosition().y;
platformBoundingBox[j].Left = sprite[i].GetPosition().x - 5;
platformBoundingBox[j].Right = sprite[i].GetPosition().x;
Window.Draw(sprite[j]);
}
}
}
}
void Map::collisions(float x, float y)
{
Player playermap;
this->x = x;
this->y = y;
playerboundingbox.Top = y - 5;
playerboundingbox.Bottom = y ;
playerboundingbox.Left = x - 5;
playerboundingbox.Right = x;
for(i = 0; i < 100; i++)
{
if(playerboundingbox.Intersects(platformBoundingBox[i]))
cout << " praise the lord";
}
}
Please switch to SFML 2 because 1.6 have a lot of bugs.
Let's say you create a class named handler where you will put:
handler::handler()
// window initialization
Map Map; // here initialize the Map class
/* why don't use Map::Map( ctor) for initialization? */
// player initialization
// run the program as long as the window is open
while (window.isOpen())
{
// check all the window's events that were triggered since the last iteration of the loop
sf::Event event;
while (window.pollEvent(event))
{
// "close requested" event: we close the window
if (event.type == sf::Event::Closed)
window.close();
}
window.clear();
//draw player
Map.DrawMap(); // also need to improve the drawing for less lag
window.display();
update(Map &Map, Player &Player);
// every time to use & because without the compiler will create another object
}
}
update(Map &Map, Player &Player)
{
// verify if exists some interacts
if (intersects(Map &Map, Player &Player))
{
//verify from where and put to the correct position
/* e.g: if we have a collide with a down tile map will say something like this:
Player.setPosition(Player.getPosition().x, (Player.getGlobalBounds().top+Player.getGlobalBounds().height)-(Map.getGlobalBounds().top-(Player.getGlobalBounds().top+Player.getGlobalBounds().height)); */
}
}
intersects(Map &Map, Player &Player)
{
sf::FloatRect fPlayer = Player.getGlobalBounds();
for (int i=0; i<Map.NrOfYourTiles; ++i)
{
sf::FloatRect fMap = YourTile.getGlobalBounds();
if (fPlayer.intersects(fMap))
return 1;
}
return 0;
}
Hope this will help you( the code is in SFML 2.0). You can find a lot more help on forums of the creator sfml-dev.org.
I wish my first post wasn't so newbie. I've been working with openframeworks, so far so good, but as I'm new to programming I'm having a real headache returning the right value from an int function. I would like the int to increment up until the Boolean condition is met and then decrement to zero. The int is used to move through an array from beginning to end and then back. When I put the guts of the function into the method that I'm using the int in, everything works perfectly, but very messy and I wonder how computationally expensive it is to put there, it just seems that my syntactic abilities are lacking to do otherwise. Advice appreciated, and thanks in advance.
int testApp::updown(int j){
if(j==0){
arp =true;
}
else if (j==7){
arp = false;
}
if(arp == true){
j++;
}
else if(arp == false){
j--;
}
return (j);
}
and then its called like this in an audioRequest block of the library I'm working with:
for (int i = 0; i < bufferSize; i++){
if ((int)timer.phasor(sorSpeed)) {
z = updown(_j);
noteOut = notes [z];
cout<<arp;
cout<<z;
}
EDIT: For addition of some information. Removed the last condition of the second if statement, it was there because I was experiencing strange happenings where j would start walking off the end of the array.
Excerpt of testApp.h
int z, _j=0;
Boolean arp;
EDIT 2: I've revised this now, it works, apologies for asking something so rudimentary and with such terrible code to go with. I do appreciate the time that people have taken to comment here. Here are my revised .cpp and my .h files for your perusal. Thanks again.
#include "testApp.h"
#include <iostream>
using namespace std;
testApp::~testApp() {
}
void testApp::setup(){
sampleRate = 44100;
initialBufferSize = 1024;
//MidiIn.openPort();
//ofAddListener(MidiIn.newMessageEvent, this, &testApp::newMessage);
j = 0;
z= 0;
state = 1;
tuning = 440;
inputNote = 127;
octave = 4;
sorSpeed = 2;
freqOut = (tuning/32) * pow(2,(inputNote-69)/12);
finalOut = freqOut * octave;
notes[7] = finalOut+640;
notes[6] = finalOut+320;
notes[5] = finalOut+160;
notes[4] = finalOut+840;
notes[3] = finalOut+160;
notes[2] = finalOut+500;
notes[1] = finalOut+240;
notes[0] = finalOut;
ofSoundStreamSetup(2,0,this, sampleRate, initialBufferSize, 4);/* Call this last ! */
}
void testApp::update(){
}
void testApp::draw(){
}
int testApp::updown(int &_j){
int tmp;
if(_j==0){
arp = true;
}
else if(_j==7) {
arp = false;
}
if(arp == true){
_j++;
}
else if(arp == false){
_j--;
}
tmp = _j;
return (tmp);
}
void testApp::audioRequested (float * output, int bufferSize, int nChannels){
for (int i = 0; i < bufferSize; i++){
if ((int)timer.phasor(sorSpeed)) {
noteOut = notes [updown(z)];
}
mymix.stereo(mySine.sinewave(noteOut),outputs,0.5);
output[i*nChannels ] = outputs[0];
output[i*nChannels + 1] = outputs[1];
}
}
testApp.h
class testApp : public ofBaseApp{
public:
~testApp();/* destructor is very useful */
void setup();
void update();
void draw();
void keyPressed (int key);
void keyReleased(int key);
void mouseMoved(int x, int y );
void mouseDragged(int x, int y, int button);
void mousePressed(int x, int y, int button);
void mouseReleased(int x, int y, int button);
void windowResized(int w, int h);
void dragEvent(ofDragInfo dragInfo);
void gotMessage(ofMessage msg);
void newMessage(ofxMidiEventArgs &args);
ofxMidiIn MidiIn;
void audioRequested (float * input, int bufferSize, int nChannels); /* output method */
void audioReceived (float * input, int bufferSize, int nChannels); /* input method */
Boolean arp;
int initialBufferSize; /* buffer size */
int sampleRate;
int updown(int &intVar);
/* stick you maximilian stuff below */
double filtered,sample,outputs[2];
maxiFilter filter1;
ofxMaxiMix mymix;
ofxMaxiOsc sine1;
ofxMaxiSample beats,beat;
ofxMaxiOsc mySine,myOtherSine,timer;
int currentCount,lastCount,i,j,z,octave,sorSpeed,state;
double notes[8];
double noteOut,freqOut,tuning,finalOut,inputNote;
};
It's pretty hard to piece this all together. I do think you need to go back to basics a bit, but all the same I think I can explain what is going on.
You initialise _j to 0 and then never modify the value of _j.
You therefore call updown passing 0 as the parameter every time.
updown returns a value of 1 when the input is 0.
Perhaps you meant to pass z to updown when you call it, but I cannot be sure.
Are you really declaring global variables in your header file? That's not good. Try to use local variables and/or parameters as much as possible. Global variables are pretty evil, especially declared in the header file like that!
I am just trying something with somebody else's code.
I have two functions:
int Triangle(Render *render, int numParts, Token *nameList, Pointer *valueList)
int i;
for (i=0; i<numParts; i++)
{
switch (nameList[i])
{
case GZ_NULL_TOKEN:
break;
case GZ_POSITION:
return putTrianglePosition(render, (Coord *)valueList[i]);
break;
}
}
return SUCCESS;
}
int putTrianglePosition(Render *render, Coord vertexList[3]) /*vertexList[3][3:xyz]*/
{
Coord *pv[3];
int i,j;
// sort verts by inc. y and inc. x
pv[0] = &vertexList[0];
pv[1] = &vertexList[1];
pv[2] = &vertexList[2];
for (i=0; i<2; i++)
for (j=i+1; j<3; j++)
{
if ((*pv[i])[1]>(*pv[j])[1] ||
(*pv[i])[1]==(*pv[j])[1] && (*pv[i])[0]>(*pv[j])[0]) {
Coord *tmp;
tmp = pv[i];
pv[i] = pv[j];
pv[j] = tmp;
}
}
;
// all y the same?
if ((*pv[0])[1] == (*pv[2])[1]) {
drawHorizonLine(render, *pv[0], *pv[2]);
return SUCCESS;
}
// assign middle point
Coord mid;
mid[1] = (*pv[1])[1]; // y
float ratio = ((*pv[1])[1] - (*pv[0])[1]) / ((*pv[2])[1] - (*pv[0])[1]);
mid[0] = (*pv[0])[0] + ratio * ((*pv[2])[0] - (*pv[0])[0]); // x
mid[2] = (*pv[0])[2] + ratio * ((*pv[2])[2] - (*pv[0])[2]); // z
if (mid[0]<=(*pv[1])[0]) { // compare X
drawTrapzoid(render, *pv[0], mid, *pv[0], *pv[1]); // upper tri
drawTrapzoid(render, mid, *pv[2], *pv[1], *pv[2]); // lower tri
}else{
drawTrapzoid(render, *pv[0], *pv[1], *pv[0], mid); // upper tri
drawTrapzoid(render, *pv[1], *pv[2], mid, *pv[2]); // lower tri
}
return SUCCESS;
}
I don't want two functions here. I want to copy the putTrianglePosition() function into the Triangle() function.
I tried doing that, but I got a lot of errors.
Can somebody else show me how to do this?
You shouldn't put functions together, you should split them apart. Put a new function wherever you can name them -- try to make them as small as you can. If you want a function that does all of that stuff, have a function that calls the other functions.
int foobar() {
int a;
int b;
/* do a whole bunch of stuff with a */
/* do a whole bunch of stuff with b */
return a + b;
}
this is sort of what you're trying to do. Instead, do this:
int foo(){
int a;
/* do a bunch of stuff with a */
return a;
}
int bar() {
int b;
/* do a bunch of stuff with b */
return b;
}
int foobar() {
return foo() + bar();
}
The result will be cleaner, easier to maintain and re-usable.
If you just change the line
return putTrianglePosition(render, (Coord *)valueList[i]);
into:
Coord* vertexList = (Coord*) valueList[i];
followed by the whole body of what's now putTrianglePosition from the opening { to the closing } included, I believe it should just work. If not, please edit your question to add the exact, complete, code as obtained by this edit and the exact, complete error messages you get.
I strongly recommend you to go with Functions because it allows better separation of logic and allows you to reuse the logic. But still in case if you want to use it that way please check the function below :
int Triangle(Render *render, int numParts, Token *nameList, Pointer *valueList)
{
int iOuter;
for (iOuter=0; iOuter<numParts; iOuter++)
{
switch (nameList[iOuter])
{
case GZ_NULL_TOKEN:
break;
case GZ_POSITION:
{
Coord* vertexList = (Coord*) valueList[i];
Coord *pv[3];
int i,j;
// sort verts by inc. y and inc. x
pv[0] = &vertexList[0];
pv[1] = &vertexList[1];
pv[2] = &vertexList[2];
for (i=0; i<2; i++)
for (j=i+1; j<3; j++)
{
if ((*pv[i])[1]>(*pv[j])[1] ||
(*pv[i])[1]==(*pv[j])[1] && (*pv[i])[0]>(*pv[j])[0]) {
Coord *tmp;
tmp = pv[i];
pv[i] = pv[j];
pv[j] = tmp;
}
}
;
// all y the same?
if ((*pv[0])[1] == (*pv[2])[1]) {
drawHorizonLine(render, *pv[0], *pv[2]);
return SUCCESS;
}
// assign middle point
Coord mid;
mid[1] = (*pv[1])[1]; // y
float ratio = ((*pv[1])[1] - (*pv[0])[1]) / ((*pv[2])[1] - (*pv[0])[1]);
mid[0] = (*pv[0])[0] + ratio * ((*pv[2])[0] - (*pv[0])[0]); // x
mid[2] = (*pv[0])[2] + ratio * ((*pv[2])[2] - (*pv[0])[2]); // z
if (mid[0]<=(*pv[1])[0]) { // compare X
drawTrapzoid(render, *pv[0], mid, *pv[0], *pv[1]); // upper tri
drawTrapzoid(render, mid, *pv[2], *pv[1], *pv[2]); // lower tri
}else{
drawTrapzoid(render, *pv[0], *pv[1], *pv[0], mid); // upper tri
drawTrapzoid(render, *pv[1], *pv[2], mid, *pv[2]); // lower tri
}
return SUCCESS;
}
break;
}
}
return SUCCESS;
}
Well, since the tag says C++ (even though the code seems to be pure C), the solution would be to put an inline modifier before the function:
inline int putTrianglePosition(Render *render, Coord vertexList[3])
{
...
}
However, even after thinking about this for ten minutes, I still fail a valid reason for wanting this.