SFML foreground collision - colors

Ive been trying to make an RPG game on SFML and now Im kind of struggling on the collisions. My problem is quiet simple, I have this 2 layers, Background and Foreground. Background just acts as a background image and Foreground png image is supposed to act as the collisions, having the part where the character is supposed to walk completely free (transparent) and keeping the rest of the structures to use as collisions (Background image here: https://imgur.com/gallery/DA3zGtD Im making the floor transparent while keeping the rest). Ive tried using the getGlobalBounds().intesect with the character sprite without any succes. I wanna keep it as simple as possible, here is what I have until now:
#include <iostream>
#include "Piso1.h"
using namespace std;
Piso1::Piso1(){
};
int Piso1::Draw(RenderWindow &window, Event &evento)
{
srand(time(nullptr));
Soundtrack.openFromFile("../Scenes/Piso1/Sounds/Neon District.wav");
Soundtrack.setLoop(true);
Soundtrack.play();
Texture BGTexture;
BGTexture.loadFromFile("../Scenes/Piso1/Graphics/piso1background.png");
Sprite Background;
Background.setTexture(BGTexture);
Background.setScale(8,7.5);
Background.setPosition(BackX,BackY);
Texture FGTexture;
FGTexture.loadFromFile("../Scenes/Piso1/Graphics/piso1foreground.png");
Sprite Foreground;
Foreground.setTexture(FGTexture);
Foreground.setScale(8,7.5);
Foreground.setPosition(BackX,BackY);
Texture ProtaTextura;
ProtaTextura.loadFromFile("../Scenes/Piso1/Graphics/pSprite.png");
IntRect SpriteBx(0,0,34,47);
Sprite Protagonista(ProtaTextura,SpriteBx);
Protagonista.setPosition((window.getSize().x)/2.35,(window.getSize().y)/3);
Protagonista.setScale(3,3);
while (window.isOpen()) {
while (window.pollEvent(evento)) {
switch (evento.type) {
case Event::Closed:
window.close();
break;
case Event::KeyPressed:
EncounterValue = rand()%1000;
if(EncounterValue > 5){
if(evento.key.code == Keyboard::Down) {
BackY -= 10;
Background.move(0,-10);
Foreground.move(0,-10);
//this is my failed attempt
if(Protagonista.getLocalBounds().intersects(Foreground.getLocalBounds()))
{
Collision.openFromFile("../Scenes/Piso1/Sounds/oof.ogg");
Collision.play();
BackY += 10;
Background.move(0, 10);
Foreground.move(0, 10);
}
if(clock1.getElapsedTime().asMilliseconds()>64){
SpriteBx.top = 0;
if (SpriteBx.left == 0)
SpriteBx.left = 34;
else if (SpriteBx.left==34)
SpriteBx.left= 68;
else if (SpriteBx.left== 68)
SpriteBx.left= 102;
else
SpriteBx.left=0;
Protagonista.setTextureRect(SpriteBx);
clock1.restart();
}
break;
}
else if (evento.key.code == Keyboard::Up) {
BackY += 10;
Background.move(0,10);
Foreground.move(0,10);
if (clock1.getElapsedTime().asMilliseconds()>64)
{
SpriteBx.top = 152;
if (SpriteBx.left == 0)
SpriteBx.left = 34;
else if (SpriteBx.left==34)
SpriteBx.left= 68;
else if (SpriteBx.left== 68)
SpriteBx.left= 102;
else
SpriteBx.left=0;
Protagonista.setTextureRect(SpriteBx);
clock1.restart();
}
break;
}
else if(evento.key.code == Keyboard::Left) {
BackX += 10;
Background.move(10,0);
Foreground.move(10,0);
if (clock1.getElapsedTime().asMilliseconds()>64)
{
SpriteBx.top = 53;
if (SpriteBx.left == 0)
SpriteBx.left = 34;
else if (SpriteBx.left==34)
SpriteBx.left= 68;
else if (SpriteBx.left== 68)
SpriteBx.left= 102;
else
SpriteBx.left=0;
Protagonista.setTextureRect(SpriteBx);
clock1.restart();
}
break;
}
else if(evento.key.code == Keyboard::Right){
BackX -= 10;
Background.move(-10,0);
Foreground.move(-10,0);
if (clock1.getElapsedTime().asMilliseconds()>64)
{
SpriteBx.top = 104;
if (SpriteBx.left == 0)
SpriteBx.left = 34;
else if (SpriteBx.left==34)
SpriteBx.left= 68;
else if (SpriteBx.left== 68)
SpriteBx.left= 102;
else
SpriteBx.left=0;
Protagonista.setTextureRect(SpriteBx);
clock1.restart();
}
break;
}
else if(evento.key.code == Keyboard::C){
Soundtrack.stop();
return 1;
}
}
else{
Soundtrack.stop();
return 0;
}
}
window.clear();
window.draw(Foreground);
window.draw(Background);
window.draw(Protagonista);
window.display();
}
}
}
I think whats happening is that when I want to do the if it takes the whole png instead of just the parts I want as collision. I also wanted to try color collision but I really dont know how to implement it, Im kind of new to SFML. Thanks in advance!

If you wish to have proper collision detection between the player and other objects .intersect() is not good enough. It will either make your character permamently stuck in the structure or make it pass through it without player control, which depends on what behavior you code for this condition.
What would work is detecting from which direction the player is approaching the object, and based on that either make him be moved back a bit or set the speed to 0 if current velocity would take him deeper into the structure.
For example, using intersect() as you are, for case of player colliding with a wall from the left:
if(velocity.x > 0 && player.getLocalBounds().intersect(wall.getLocalBounds()) && player.getLocalBounds().left > wall.getLocalBounds().left)
Then you can use this condition to either stop the player (set the velocity.x to 0), set reverse it so he backs off or do any other kind of behavior you'd wish in the event of a collision.
(Note this is not an ideal solution, but it should work and follow similar logic you've implemented.)

Related

How to make a sprite with fixed movement distance in Phaser

I have a grid-based top-down game with arcade physics and I'd like my player to move precisely between grid positions. But how can I do this?
I'm moving the player now on keydown using velocity, then resetting the velocity to 0 on update so there's no inertia.
function update(){
this.player.body.velocity.x = 0
this.player.body.velocity.y = 0
if(this.keyIsLeft){
this.player.body.velocity.x -= 200
}
else if(this.keyIsRight){
this.player.body.velocity.x += 200
}
else if(this.keyIsUp){
this.player.body.velocity.y -= 200
}
else if(this.keyIsDown){
this.player.body.velocity.y += 200
}
But how can I get the player to only move a square (or half square) at a time?
The ideal movement is shown here in this Lolo game, where at any given time the player is on a grid or half-grid space: https://www.youtube.com/watch?v=QQKScIJYUxU&t=5m30s
I can't just set the x and y position or use tweening because I need to keep arcade physics, and those adjustments interfere with them.
Updated:
Here is my updated Answer to solve this case.
I implemented this method based on the example provided by Phaser.
The key part to making this fixed movement happen is to disable the keyboard input while the item is moving.
Let's say if you pressed left key, the player is moving towards left. While the player starts moving, you set a variable notMoving to false, which notifies the update function to not take any cursor inputs. After a timeout, let's say 1000ms, you can set the variable notMoving to true. Then the update function will continue take the cursor input.
Here is the example code snippet:
function create ()
{
cursors = this.input.keyboard.createCursorKeys();
player = this.physics.add.image(400, 300, 'block');
player.setCollideWorldBounds(true);
player.setData('notMoving', true);
}
function setfixedMovement(velocity, direction) {
if (direction === 'up') {
player.setVelocityY(-velocity);
} else if (direction === 'down') {
player.setVelocityY(velocity);
} else if (direction === 'left') {
player.setVelocityX(-velocity);
} else {
player.setVelocityX(velocity);
}
player.setData('notMoving', false);
setTimeout(() => {
player.setData('notMoving', true);
}, 1000);
}
function update () {
if (player.getData('notMoving')) {
player.setVelocity(0);
if (cursors.left.isDown) {
setfixedMovement(300, 'left');
} else if (cursors.right.isDown) {
setfixedMovement(300, 'right');
}
if (cursors.up.isDown) {
setfixedMovement(300, 'up');
} else if (cursors.down.isDown) {
setfixedMovement(300, 'down');
}
}
}
I put the phaser example link in the previous answer. If you edit the example and replace the part of example code with the snippet I provided above, you can see it working as you expected.
Previous Answer:
I think what this phaser example does exactly what you want to do
In short,
in each update, set the velocity to 0,
then detect the check the cursor key status and set the velocity accordingly
the following code is copied from Official Phaser 3 Example
function update ()
{ player.setVelocity(0);
if (cursors.left.isDown)
{
player.setVelocityX(-300);
}
else if (cursors.right.isDown)
{
player.setVelocityX(300);
}
if (cursors.up.isDown)
{
player.setVelocityY(-300);
}
else if (cursors.down.isDown)
{
player.setVelocityY(300);
}
}
Here is the link to the example
https://labs.phaser.io/view.html?src=src\input\keyboard\cursor%20keys.js

Exception thrown at 0x00000000 in ConsoleApplication1.exe: 0xC0000005: Access violation executing location 0x00000000

After people told me to shorten the program I did it and here is the shortened version of the program with the same error as stated above.It only appears after a few moments into the program.If i hit continue the program works fine.However see the movement function?It does't work.The sprite refuses to move in any direction.However if i give a very large floating value in the move,then the sprite is displaced from it's position when i start the program and it stays there in that position with no further movement.For example if i write sprite.move(400.f,400.f) the sprite moves from (0,0) to (400,400) and stays there.It doesn't move any more.
Here's the shortened version of the code:
#include"SFML\Graphics.hpp"
#include<iostream>
int main()
{
sf::RenderWindow window(sf::VideoMode(640, 480), "CHECK",sf::Style::Default);
std::cout << "WORKS";
sf::Texture text;
text.loadFromFile("bahamut.png");
sf::Sprite sprite;
sf::Clock frap;
sprite.setTexture(text);
while (window.isOpen())
{
float fps = frap.restart().asSeconds();
sf::Vector2f movements;
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::A))
{
movements.y = 0;
movements.x = -1 * fps;
}
else
{if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::D))
{
movements.y = 0;
movements.x = 1 * fps;
}
else
{ if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::S))
{
movements.y = 1 * fps;
movements.x = 0;
}
else
{
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::W))
{
movements.y = -1 * fps;
movements.x = 0;
}
else
{
movements.x = 0;
movements.y = 0;
}
}
}
}
sprite.move(movements);
window.clear();
window.draw(sprite);
window.display();
}
return 0;
}
I improved upon the code and it still produces the same results and error.
On using the dissassembler i saw the crash occurs at
00B37AEE cmp esi,esp
in window.display().
when i create a function and use it to display the sprite,the movement occurs but witthout the unction nada
Your logic says your movement is 0/0 if W is not pressed. The else of the W pressed block overrides all prior settings. And moving the sprite should happen before you display.
I cannot see a reason for the null pointer exception, but that is what the debugger is for. Next time this happens, debug.
Oh and it's int main(), not void. I know the compiler tolerates this error, but it's still an error and undefined behavior.

Unity3D nothing but distortion when playing audio clips

I'm having a lot of trouble with playing audio clips. I suspect it has something to do with update playing my clip from the start every time it executes the block of code that sends the clip to the audio source. Below is a 'solution' but the fact that it works doesn't even make sense to me. If I just put the audio.play() in the main if statement without checking whether it's less than the audio clip length, I hear nothing but a quiet distortion.
void Update()
{
switch(weatherState)
{
case WeatherStates.Sunny:
break;
case WeatherStates.Rain:
Rain();
break;
case WeatherStates.Snow:
break;
case WeatherStates.ThunderStorm:
break;
}
}
void Rain()
{
if(timeScript.hourOfWeatherEvent != 0)
{
if(timeScript.hourCount >= timeScript.hourOfWeatherEvent)
{
rain.SetActive(true);
if(soundCount < weatherSounds[0].length)
{
soundCount++;
audio.clip = weatherSounds[0];
audio.Play ();
}
timeScript.durationOfWeatherEvent -= Time.deltaTime * timeScript.timeSpeed;
if(timeScript.durationOfWeatherEvent <= 0)
{
rain.SetActive(false);
timeScript.durationOfWeatherEvent = 0;
timeScript.hourOfWeatherEvent = 0;
weatherState = WeatherStates.Sunny;
}
}
}
}

opencv capture image from webcam without post processing

I want to capture images from webcam without any post processing, that is NO auto focus , exposure correction , white balance and stuff. Well basically I want to capture continuous frames from webcam and make each frame compare with the previous one and save them to disk only when there is an actual change. Because of the post processing almost every frame is being returned as different for me.
code so far
using namespace cv;
bool identical(cv::Mat m1, cv::Mat m2)
{
if ( m1.cols != m2.cols || m1.rows != m2.rows || m1.channels() != m2.channels() || m1.type() != m2.type() )
{
return false;
}
for ( int i = 0; i < m1.rows; i++ )
{
for ( int j = 0; j < m1.cols; j++ )
{
if ( m1.at<Vec3b>(i, j) != m2.at<Vec3b>(i, j) )
{
return false;
}
}
}
return true;
}
int main() {
CvCapture* capture = cvCaptureFromCAM( 1);
int i=0,firsttime=0;
char filename[40];
Mat img1,img2;
if ( !capture ) {
fprintf( stderr, "ERROR: capture is NULL \n" );
getchar();
return -1;
}
cvNamedWindow( "img1", CV_WINDOW_AUTOSIZE );
cvNamedWindow( "img2", CV_WINDOW_AUTOSIZE );
while ( 1 ) {
IplImage* frame = cvQueryFrame( capture );
img1=frame;
if ( !frame ) {
fprintf( stderr, "ERROR: frame is null...\n" );
getchar();
break;
}
if(firsttime==0){
img2=frame;
fprintf( stderr, "firtstime\n" );
}
if ( (cvWaitKey(10) & 255) == 27 ) break;
i++;
sprintf(filename, "D:\\testimg\\img%d.jpg", i);
cv::cvtColor(img1, img1, CV_BGR2GRAY);
imshow( "img1", img1);
imshow( "img2", img2);
imwrite(filename,img1);
if(identical(img1,img2))
{
//write to diff path
}
img2=imread(filename,1);
firsttime=1;
}
// Release the capture device housekeeping
cvReleaseCapture( &capture );
return 0;
}
While ur at it, I'll be great full if u can suggest a workaround for this using another frame compare solution aswell :)
I had this problem, and the only solution that found and wrote was a program based on Direct-show (in case you're using windows )so no opencv code at all
with a bit of luck, you can get the properties page of your camera, and switch things off there:
VideoCapture cap(0);
cap.set(CV_CAP_PROP_SETTINGS,1);
and please, skip the c-api in favour of c++. it'll go away soon.
forgot to mention : you an change the cam-settings from vlc as well.
#Prince, sorry I have been looking for my Directshow code I didn't found it, and I don't think it will help because I used it for the DirectLink (Black magic Design)card, since I've never did that befor it was pretty hard, my suggestion will be try to use GraphEditPlus :
http://www.infognition.com/GraphEditPlus/
it helps a lot, and it's easy to use !
good luck !
If you just wish to capture frames when there is an actual change, try background subtraction algorithms. Also, instead of just subtracting subsequent frames, use one of the many algorithms already implemented for you in OpenCV - they are much more robust to changes in lightning conditions etc than vanilla background subtraction.
In Python :
backsub = cv2.BackgroundSubtractorMOG2(history=10000,varThreshold=100)
fgmask = backsub.apply(frame, None, 0.01)
Frame is the stream of pictures read from your webcam.
Google for the corresponding function in Cpp.

How to properly implement cheat codes?

what would be the best way to implement kind of cheat codes in general?
I have WinForms application in mind, where a cheat code would unlock an easter egg, but the implementation details are not relevant.
The best approach that comes to my mind is to keep index for each code - let's consider famous DOOM codes - IDDQD and IDKFA, in a fictional C# app.
string[] CheatCodes = { "IDDQD", "IDKFA"};
int[] CheatIndexes = { 0, 0 };
const int CHEAT_COUNT = 2;
void KeyPress(char c)
{
for (int i = 0; i < CHEAT_COUNT; i++) //for each cheat code
{
if (CheatCodes[i][CheatIndexes[i]] == c)
{ //we have hit the next key in sequence
if (++CheatIndexes[i] == CheatCodes[i].Length) //are we in the end?
{
//Do cheat work
MessageBox.Show(CheatCodes[i]);
//reset cheat index so we can enter it next time
CheatIndexes[i] = 0;
}
}
else //mistyped, reset cheat index
CheatIndexes[i] = 0;
}
}
Is this the right way to do it?
Edit: Probably the worst thing I should have done was to include the first cheat codes that came from the top of my head as an example. I really did not want to see Doom's source code or their implementation, but general solution to this problem.
Why not download the DOOM source and see for yourself? =)
http://www.doomworld.com/idgames/?id=14576
I think this one's a bit easier to understand, though your original will probably perform better than this one:
using System.Collections.Generic;
void KeyPress(char c)
{
string[] cheatCodes = { "IDDQD", "IDKFA"};
static Queue<char> buffer; //Contains the longest number of characters needed
buffer.Enqueue(c);
if (buffer.Count() > 5) //Replace 5 with whatever your longest cheat code is
buffer.Dequeue();
bufferString = new System.String(buffer.ToArray());
foreach(string code in cheatCodes) {
if (bufferString.EndsWith(code)) {
//Do cheat work
}
}
}
here is the DOOM cheat implementation from the doom source:
#define SCRAMBLE(a) \
((((a)&1)<<7) + (((a)&2)<<5) + ((a)&4) + (((a)&8)<<1) \
+ (((a)&16)>>1) + ((a)&32) + (((a)&64)>>5) + (((a)&128)>>7))
int cht_CheckCheat ( cheatseq_t* cht, char key )
{
int i;
int rc = 0;
if (firsttime)
{
firsttime = 0;
for (i=0;i<256;i++) cheat_xlate_table[i] = SCRAMBLE(i);
}
if (!cht->p)
cht->p = cht->sequence; // initialize if first time
if (*cht->p == 0)
*(cht->p++) = key;
else if
(cheat_xlate_table[(unsigned char)key] == *cht->p) cht->p++;
else
cht->p = cht->sequence;
if (*cht->p == 1)
cht->p++;
else if (*cht->p == 0xff) // end of sequence character
{
cht->p = cht->sequence;
rc = 1;
}
return rc;
}

Resources