Jump to content

  • Log In with Google      Sign In   
  • Create Account

Khatharr

Member Since 24 Apr 2010
Offline Last Active Private

#5290329 pong game ball reflecting (C++ SFML)

Posted by Khatharr on 05 May 2016 - 03:54 PM

So 45 degrees points toward the bottom-right corner of the screen?
damn, all this time i based the angle from cartesian plane, i didnt know 45 degrees would be in bottom-right i thought it was upper right. but i guess its still the same

 

The unit circle assumes upward Y. If Y is downward you have to flip the circle over so that +X and +Y are in the right directions.

 

 

I'm not going to look at (or run) external code due to a lack of interest.
i mean play the ponggame.org, you can see there wht im trying to achieve

 

This didn't help me. I don't have the patience to sit here and play a Pong clone long enough to dissect the paddle reactions during gameplay. If you would explain exactly what you want to happen it would probably help both of us.
 

 

What if the ball hits the paddle and is deflected, but then is still in collision with the paddle on the next frame?
i already experienced this many times in this pong game, thats why the reflection logic and pongball.move() are on the same function so it can avoid that from happening

 

What? Anyway, correcting the problem would be better than working around it.

 

 

Negating the angle makes no kind of sense
like i said i based it from ponggame.org when i was playing it  i realized when the ball hits the lower part of player1's paddle at angle 91-269 its just negated it, same with player2  paddle

 

Negating the angle is going to flip vertically. Think about 45 degrees vs -45 degrees.

negate.jpg

 

 

 speed and not angle speed{x,y}
what do you mean about this? my speed vector is just the speed of the ball. actually im using a vector with only x and y and operators overloaded with it

 

Vector representations:

struct Vector2D {
  float angle;
  float length;
};

//or

struct Vector2D {
  float x, y;
};

//NOT
struct Vector2D {
  float angle;
  float x, y;
};

Consider this:

speed.x * cos(angle*Ball::pi/180)*delta

First off, you're not altering speed.x anywhere. You're not using the magnitude of speed, but only the magnitude of the x speed. cos() is going to give you the X side of your x:y ratio for the angle you feed it. sin() will give you the Y side. Those both need to be scaled by the same number (the magnitude or "speed") in order to make sense. {cos(angle), sin(angle)} will give a normalized (length of 1) direction vector {x,y}. You multiply that vector by the speed to get the scaled {x,y} that represents the actual velocity. You then multiply that by the time delta to get the displacement vector for that frame. (or you can multiply it by the speed before doing the vector math)

 

 

 

Can you explain what you want to have happen when it hits the paddle?
my function is doing fine, but i still dont have the logic when it hits the middle and the edges of the paddle.
but it looks like im doing it very wrong, can you tell me a more standard way of doing this pong game?
you know im really really newbie in game dev.  as you see my class design is bad too(but nvm that)

 

The simplest way to do it is to use an x,y vector and just negate x when it touches a paddle && is moving toward that paddle's side of the board. (And negate y when it hits a wall.)

 

I think you're wanting to do some deflection based on what part of the paddle it hits though, so that won't work here. I still want you to describe exactly what kind of reactions you want. You have some kind of input-process-output in mind, but it's not clear to me and I think it's not fully clear to you. Draw me a picture and explain the input and output it in detail and I think the process will become obvious.

 

If not then it will at least provide a clear vocabulary for discussing the specifics of the problem.
 

 

can we do it while avoiding trigo?

 

The alternative is changing the behavior to not use any angles (as described above), but I don't think that's what you're asking for. That system can be tweaked a little bit based on other factors, but I really want to know what the target behavior is first.




#5290199 Is it C# Territory?

Posted by Khatharr on 05 May 2016 - 12:33 AM

That sounds an awful lot like comparing the expected results of the new product against the quality of the existing product to see if the value of improvement exceeds the implementation cost and risks.




#5290172 Is it C# Territory?

Posted by Khatharr on 04 May 2016 - 06:51 PM

Your good reason is "We have hundreds of thousands of man hours invested in our giant aging C++ code base, thus we'll be keeping that around. kthxbye."

 

Sunk cost fallacy...

 

A good reason would involve comparing the expected results of the new product against the quality of the existing product to see if the value of improvement exceeds the implementation cost and risks.




#5290161 Time - the most important factor.

Posted by Khatharr on 04 May 2016 - 05:21 PM

Hey, folks. <sardonic half-smile>

 

This is the 'For Beginners' forum.

 

You may feel some rustled jimmies because OP didn't start the thread by kissing our collective ass and worshiping us for the amount of work and effort that goes into making games, but consider that there's no way for a non-dev to know anything about that, especially in a media climate that actively reinforces the 'no effort' delusion at every opportunity.

 

In any case, let's not downvote him for asking why. The beginner forum is for people who don't know things to learn. It's not appropriate to punish him for not knowing something, especially when he's challenging his ignorance by recognizing the disparity and asking about it.




#5290152 pong game ball reflecting (C++ SFML)

Posted by Khatharr on 04 May 2016 - 05:00 PM

Y+ will go to down side
X+ will go to right side

 
So 45 degrees points toward the bottom-right corner of the screen?
 

try play it and you will see it would do same thing

 
I'm not going to look at (or run) external code due to a lack of interest.
 
 

Looking at the last line from OP, I see
 

speed.x * cos(angle*Ball::pi/180)*delta
speed.y * sin(angle*Ball::pi/180)*delta

Which tells me

  • You like verbose operations rather than saving pi/180 as a constant somewhere.
  • No rotation or flipping is being applied to the trig, so 45 degrees should be down-right or else there's a problem.
  • This operation is wrong anyway because you're multiplying velocity vector elements instead of velocity vector magnitude. (Unless that's there to stretch the board, in which case: Don't do that.)

Then when I look at the segment that you repeated I see:

        if ( pongball.getPosition().y < p1.getPad().getPosition().y ) {
            if ( angle > 90 && angle < 180 ) { 
                angle = 180 - angle;
            }
            else {
                angle = -angle;
            }
        }

You said P1 is on the left, so 90 to 270 could represent a collision against the inward wide face of the paddle. You're using volumetric collision, though, so you're not considering:

  1. What if the ball hits the narrow face of the paddle?
  2. What if the ball hits the paddle and is deflected, but then is still in collision with the paddle on the next frame?

Further, scribbling this on paper I see some problems with the angle manipulation:

 

90 - 180 degrees is the down-left quadrant. 180 - angle will deflect acceptably because it's just negating the X speed.

 

180 - 270 degrees is the up-left quadrant. Negating the angle makes no kind of sense. Figure an angle of 185 degrees. Negated that's 360-185 = 175. 175 is still a very leftward angle. In fact, it's a negation of the Y speed, which would only make sense if you struck the top or bottom surface of the paddle, but that's not what you're testing for here.

 

Fixing (some) things:

 

First you need to decide what this function is doing. Right now it's trying to do collision and motion, and since you're passing in a RenderWindow I'm guessing you're thinking about tossing in drawing as well. You need to break this up a bit.

 

Secondly - while I would much prefer that you use an x,y vector for velocity and not touch angles at all - if you do use angles then you need to have angle, speed and not angle speed{x,y}. Your last line should look more like this:

float radians = degToRad(angle);
float distance = speed * delta;
move(distance * cos(radians), distance * sin(radians));

.

Thirdly, you're referring to some object called 'pongball' throughout this function. That looks like a very bad thing, since this function is a member of 'Ball'. What's going on with that?

 

Fourthly, I don't know what's actually intended with your angle manipulation. There's no circumstance where a ball striking a vertical surface should experience a flip its y value. It would be forced to tunnel into the wall because of the way the code is structured, and then it's going to get stuck in there because it's penetrating by 2 frames worth of distance and every frame it will continue to collide and get 'jostled' around inside the paddle. Can you explain what you want to have happen when it hits the paddle? Please use pictures if necessary.




#5290142 how good is rand() ?

Posted by Khatharr on 04 May 2016 - 04:19 PM

Not all that good.
If you have access to C++11 and the STL, try the "<random>" header.

#include <random>

void main(void)
{
    // the random-device/generator, there is a few different of those
    // you create one at the start of your application, or multiple if you want to seperate RNG of different components
    std::mt19937 randgen((unsigned int)time(nullptr));
    
    // the distribution, there are different types for float, int, ...
    // you can create this on-the-fly inside a function
    const std::uniform_int_distribution<int> distribution(0, 1024);
    
    const auto randomNumber = distribution(randgen);
}
You are supposed to get way better results with that.

 


Don't seed mt with timer. -.-
 
random_device is true-random (check your impl docs though if you require true rand or crypto-secrure) and will provide a much better seed value. Plus you don't have to include anything else (especially anything from stdlib).

std::mt19937 mt(std::random_device{}());

.

It's a hell of a lot faster than a Mersenne Twister.


I have a hard time believing that this is a real-world problem in a games context.


For OP: https://channel9.msdn.com/Events/GoingNative/2013/rand-Considered-Harmful




#5289955 pong game ball reflecting (C++ SFML)

Posted by Khatharr on 03 May 2016 - 03:16 PM

This looks incorrect in many different ways...

 

Before launching into all of that, though, what is the angle orientation here? It looks like there's trig going on, which would suggest that 0 is toward X+ (which is rightwards, I hope), but what direction is Y+? Also, which paddle is on which side?




#5289954 Time - the most important factor.

Posted by Khatharr on 03 May 2016 - 03:00 PM

This is a question you could probably answer for yourself if you wanted. Try making a clone of SV and then factor in time for asset creation, design, redesign, etc.




#5289617 Is making game with c possible?

Posted by Khatharr on 01 May 2016 - 02:29 PM

Don't worry about it.  Go write games.

 

QFE. C vs C++ is a bloodied and savage battlefield populated by extremely powerful idiots. Thar be dragons.




#5289467 I Have a Problem in "char *" & "LPCWSTR"

Posted by Khatharr on 30 April 2016 - 03:19 PM

Incidentally, if you want to represent either LPSTR and LPWSTR depending on compiler settings you can use LPTSTR.




#5289159 Detect if someone is live-streaming the game

Posted by Khatharr on 28 April 2016 - 05:01 PM

I think it's worth pointing out that there are people that would be offended by a game that sniffs around the system and tries to figure out what other programs are doing. (I'm one of them.) Telling those people that it's to help them would make the problem worse rather than better.

 

Be careful about things like this.




#5288553 Noob pointer question

Posted by Khatharr on 25 April 2016 - 01:00 AM

An analogy:

 

The stack is a literal stack of small boxes on your desk. Each box represents a function, with the box on the bottom being main(). Each box contains some pieces of paper that represent the local variables of the function. The values of those variables are written on the papers. When main() calls a function the box for that function gets placed (stacked) on top of main() and its variables are placed in it. When that function exits its box is removed and its variables go along with it, so that the box on top of the stack is always the currently executing function. This is effectively how the stack works.

 

Now the heap is a filing cabinet in the desk drawer. There are no boxes here. Instead there is a long, ordered stack of re-usable papers. Each one is numbered in order. You cannot remove these papers, but you can look them up by number and read or write any of them. In order to avoid accidentally writing over something that you're storing in there, you have a set of paper clips. When you want to use a paper in the drawer, you put a paper clip on it and then write down its number on a note and put that note in the top box. This is the allocation process. In fact, you have a secretary called 'new' that does this for you. You tell the secretary how many pages you need and the secretary finds an appropriate set of pages, paperclips them and tells you the number of the first one. The paper that you're writing the number on is a pointer. The number itself is an address. When you're done using heap memory you tell the number you wrote down to the secretary (using 'delete') and they remove the clip from that allocation so that it can be used again later.

 

The important thing to remember is that the pointer is a paper in the box and the address is the number that refers to a page in the drawer.

 

Where it gets a little confusing is that memory isn't really separated this way. The stack is actually just a data structure that's extending into memory. Pointers are just a special numeric type. It's perfectly legal to have a pointer to a stack variable. It's perfectly legal to have a pointer with any value you want. It's just a piece of paper in the box with a number written on it.

 

Consider the following:

int* allocation = new int[3]; //reserve enough memory for 3 ints and store the address in 'allocation'
int* ptr = allocation; //copy the address in 'allocation' into 'ptr'
*ptr = 1; //set the value of the memory at 'ptr' to 1
ptr++; //increase the vale of ptr - note that this is making ptr point to a different address, not changing the '1' that we just wrote
*ptr = 2; //set the value of the memory at 'ptr' to 2
ptr++; //increase the vale of ptr
*ptr = 3; //set the value of the memory at 'ptr' to 3
delete allocation; //release the allocation pointed to by 'allocation'
//note that if we tried to delete ptr there would be an error because it no longer points to the base of the allocation

If you freeze the program at this point then the memory there should still contain 1,2,3 in order (because nothing has written over it yet).

'allocation' will still point to the '1' and 'ptr' will still point to the '3'.

 

The memory is no longer reserved. If the program allocates more memory later there's a decent chance that it will re-use this area of memory and change the values there. Since the reservation is gone the memory in question is 'fair game' to be reallocated.

 

Since the memory is no longer reserved, calling delete on 'allocation' again should cause an error because there's no reservation recorded for that address. However, it's possible to get some 'fun' if something else asks for memory and a new allocation starts at that same address. In that case an extra delete will destroy the new allocation, so don't rely on getting explicit errors (you almost always will in practice, though).

 

It is legal to delete zero, or nullptr, even though they will never be the base of an allocation. Relying on this for general use is a bad plan. There are some cases where it's useful, but avoid the bad habit of always setting pointers to null after releasing their allocations. If you can't resist setting the pointer then set them to 0x0BAD0BAD or something similar that will provide a recognizable error if you try to release them again. Error messages are good. They tell you something is wrong, and that's something that you want to know about, so in general try to avoid behaviors that obfuscate errors.




#5287506 Memory Allocation

Posted by Khatharr on 18 April 2016 - 12:48 PM

sizeof(Node)

Don't repeat the struct keyword everywhere or I will hunt you down and take all the vowels from your keyboard.


#5287340 Direct3D9 Debugging on windows 10.

Posted by Khatharr on 17 April 2016 - 12:56 PM

I can get it working on 7 but it harms the functionality of the OS. I just don't want OP to go through all that if it can be avoided. And yes, Nsight works great with 9.




#5287271 Direct3D9 Debugging on windows 10.

Posted by Khatharr on 17 April 2016 - 01:35 AM

Not using DX9 would be a great start. Is this an external requirement?






PARTNERS