Learning SFML and making a game in C++ for the first time. My problem comes with movement of the character. I'm making an Astroids-like clone, and the movement, when the keys are pressed, aren't very smooth. The character stutters around, and stops when rotating and moving forward are pressed at the same time. Any help?
Player.cpp
#include "Player.h"
#include "Bullet.h"
#include <iostream>
#include <valarray>
#define SPEED 10
#define ROTATION 15
Player::Player()
{
this->_x = 150;
this->_y = 150;
this->_xspeed = 0;
this->_yspeed = 0;
this->_rotation = ROTATION;
this->_user = this->loadSprite("/Users/ganderzz/Desktop/Programming/C_Plus/stest/stest/Resources/Player.png");
this->_user.setOrigin(16, 16);
}
void Player::Collision(RenderWindow & in)
{
if(this->_x >= (in.getSize().x-32) || this->_x <= 0)
this->_xspeed = 0;
}
void Player::Move(Event & e)
{
if(Keyboard::isKeyPressed(Keyboard::D))
{
this->_user.rotate(this->_rotation);
}
if(Keyboard::isKeyPressed(Keyboard::A))
{
this->_user.rotate(-this->_rotation);
}
if(Keyboard::isKeyPressed(Keyboard::W))
{
this->_yspeed = -sinf((90 + this->_user.getRotation()) * 3.14 / 180) * SPEED;
this->_xspeed = -cosf((90 + this->_user.getRotation()) * 3.14 / 180) * SPEED;
this->_x += this->_xspeed;
this->_y += this->_yspeed;
}
if(Keyboard::isKeyPressed(Keyboard::Space))
{
Bullet b(this->_x,this->_y,this->_user.getRotation());
}
}
void Player::Draw(RenderWindow & in)
{
this->_user.setPosition(this->_x, this->_y);
in.draw(this->_user);
}
Sprite Player::loadSprite(std::string filename)
{
this->_texture.loadFromFile(filename, IntRect(0,0,32,32));
return Sprite(this->_texture);
}
I think it is due to time management, if it is a small 2D you probably have a high FPS rate.
And then your move event is call way to many times and create this stutter.
You should limit you framerate, and try to add a clock to your event if limiting framerate is not enough.
You can find what you need in this page of the doc
If it is not that at all, show us your main loop, maybe you have something taking a lot of ressources there.
Hope it helps.
Related
notes:
room1Collisions is a 1D array containing 1s and 0s representing collidable tiles.
+/- 0.1 is used so that the player can still move when against a collidable tile.
size is an SFML vector that holds the width and height of the player.
I understand that this code is not in great shape, but I'm trying to get collisions working to then refactor.
The issue (described below) occurs more frequently when the player collides diagonally
code:
void Player::Update(float dt) {
// 0 is a collidable tile
// change room1Collisions to a pointer of current level
if (sf::Keyboard::isKeyPressed(sf::Keyboard::A))
{
// a is top left and b is bottom left
sf::Vector2u a(position.x/tileSize.x, (position.y+size.y/2)/tileSize.y);
sf::Vector2u b(position.x/tileSize.x, (position.y+size.y-0.1)/tileSize.y);
int tileNumberA = room1Collisions[(a.x) + a.y*(tilemapBounds.x/tileSize.x)];
int tileNumberB = room1Collisions[(b.x) + b.y*(tilemapBounds.x/tileSize.x)];
if (tileNumberA != 0 && tileNumberB != 0 && position.x >= 0) {
position.x -= speed * dt;
//animation.resumeAnimation();
}
direction = LEFT;
//animation.resumeAnimation();
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::D))
{
sf::Vector2u a((position.x+size.x)/tileSize.x, (position.y+size.y/2)/tileSize.y);
sf::Vector2u b((position.x+size.x)/tileSize.x, (position.y+size.y-0.1)/tileSize.y);
int tileNumberA = room1Collisions[(a.x) + a.y*(tilemapBounds.x/tileSize.x)];
int tileNumberB = room1Collisions[(b.x) + b.y*(tilemapBounds.x/tileSize.x)];
if (tileNumberA != 0 && tileNumberB != 0 && position.x+size.x <= tilemapBounds.x) {
position.x += speed * dt;
//animation.resumeAnimation();
}
direction = RIGHT;
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::W))
{
sf::Vector2u a((position.x+0.1)/tileSize.x, (position.y+(size.y/3))/tileSize.y);
sf::Vector2u b((position.x+size.x-0.1)/tileSize.x, (position.y+(size.y/3))/tileSize.y);
int tileNumberA = room1Collisions[(a.x) + a.y*(tilemapBounds.x/tileSize.x)];
int tileNumberB = room1Collisions[(b.x) + b.y*(tilemapBounds.x/tileSize.x)];
if (tileNumberA != 0 && tileNumberB != 0 && position.y >= 0) {
position.y -= speed * dt;
//animation.resumeAnimation();
}
direction = UP;
//animation.resumeAnimation();
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::S))
{
sf::Vector2u a((position.x+0.1)/tileSize.x, (position.y+size.y)/tileSize.y);
sf::Vector2u b((position.x+size.x-0.1)/tileSize.x, (position.y+size.y)/tileSize.y);
int tileNumberA = room1Collisions[(a.x) + a.y*(tilemapBounds.x/tileSize.x)];
int tileNumberB = room1Collisions[(b.x) + b.y*(tilemapBounds.x/tileSize.x)];
if (tileNumberA != 0 && tileNumberB != 0 && position.y+size.y <= tilemapBounds.y) {
position.y += speed * dt;
//animation.resumeAnimation();
}
direction = DOWN;
}
//animation.setAnimation(direction);
//animation.Update(dt, 0.2f);
//animation.setPosition(position);
box.setPosition(position);
}
The problem is that when the game is run on slower computers, sometimes the player will skip (?) a collision check and it becomes stuck in a collidable tile, preventing it from moving orthogonally with respect to the collidable tile. On faster computers this issue is not present unless the player speed (currently 30) is increased significantly.
Below is an image showing the player inside a collidable tile. Please note that in this example the player is not able to move left/right since those directions are perpendicular to the collidable tile, but can still move up.
What you need is to regulate the FPS so that it is consistent for all computers.
Frame rate regulation example(This uses the SDL2 library for SDL_GetTicks and SDL_Delay but there are probably alternatives to that depending on your graphics library):
const int FPS = 60;
const int frameDelay = 1000/FPS;
Uint32 frameStart;
int frameTime;
//Main game loop
while (true)
{
//Gets the amount of milliseconds elapsed since the program was first run
frameStart = SDL_GetTicks();
//YOUR MAIN GAME LOOP HERE
//Gets the amount of milliseconds that it took to run the game loop
frameTime = SDL_GetTicks() - frameStart;
//Checks if the game loop was run faster than the max frame time
if(frameDelay > frameTime)
{
//Delays the game loop so that it takes that the frame time always is the same
SDL_Delay(frameDelay - frameTime);
}
}
(Keep in mind that this is just an example there are lots of ways to regulate the FPS)
After implementing FPS regulation you might need to tweak the speed and collision sensitivity a little but once you have it it should be consistent on ALL computers
Sorry for the massive block of code ;w;
I'm learning C++, and this is an assignment I'm stuck on- I'm supposed to be making a brick wall with alternating rows offset by 1/2 bricks, and I'm supposed to be using a nested loop to do so.
I've got the functions to draw the full brick and half bricks, and I've successfully been able to create a full line of 9 bricks(9 being how many bricks can span the window) and I'm stuck on the next step. I need to make the program draw the next line after the first one is finished, but "\n" and "cout << endl;" only affect the main window and not the "TurtleWindow" that OpenCV opens. All I have in that regard is that it has something to do with the "changePosition" command, but I'm not sure how to add that in to my loop. If I set position to some specific (x, y) coords, then wouldn't it just keep setting the "bricks" in that position every loop?
Any help would be appreciated, I feel like I'm so close to the solution but this is stumping me...
// BrickWall.cpp : This file contains the 'main' function. Program execution begins
//and ends there.
//
#include <iostream>
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include <stdio.h>
#include <math.h>
using namespace cv;
using namespace std;
#define M_PI 3.14159265358979323846264338327950288
#define degToRad(angleInDegrees) ((angleInDegrees) * M_PI / 180.0)
char wndname[] = "TurtleWindow";
Mat image = Mat::zeros(500, 500, CV_8UC3);
Scalar WHITE(255, 255, 255);
const int DELAY = 1;
Point _curPosition(250, 250);
int _direction = 0;
void init()
{
imshow(wndname, image);
waitKey(DELAY);
}
//
// Move the pen to the given coordinates without leaving a mark
//
// Note (0,0) refers to the upper left corner
// (500,500) refers to the bottom right corner
//
void changePosition(int x, int y)
{
_curPosition.x = x;
_curPosition.y = y;
}
//
// point in the direction given in degrees
// 0 ==> point right
// 90 ==> point down
// 180 ==> point left
// 270 ==> point up
//
void changeDirection(int direction)
{
_direction = direction;
}
//
// Moves the pen forward the given number of pixels
// Note leaves a mark creating a line from the previous point
// to the new point
//
void moveForward(int nPixels)
{
int x = static_cast<int>(round(nPixels * cos(degToRad(_direction))));
int y = static_cast<int>(round(nPixels * sin(degToRad(_direction))));
Point newPoint = Point(x + _curPosition.x, y + _curPosition.y);
line(image, _curPosition, newPoint, WHITE);
_curPosition = newPoint;
// cout << "moved to " << newPoint.x << "," << newPoint.y << endl;
imshow(wndname, image);
waitKey(DELAY);
}
void fullBrick()
// changePosition(25, 25);
{
changeDirection(0);
moveForward(50);
changeDirection(90);
moveForward(20);
changeDirection(180);
moveForward(50);
changeDirection(270);
moveForward(20);
changeDirection(0);
moveForward(50);
}
void halfBrick()
//changePosition(25, 45);
{
changeDirection(0);
moveForward(25);
changeDirection(90);
moveForward(20);
changeDirection(180);
moveForward(25);
changeDirection(270);
moveForward(20);
}
int main()
{
int counter;
int counterWall;
counterWall = 0;
counter = 0;
init();
changePosition(25, 25);
while (counter < 20)
{
do
{
changeDirection(0);
moveForward(50);
changeDirection(90);
moveForward(20);
changeDirection(180);
moveForward(50);
changeDirection(270);
moveForward(20);
changeDirection(0);
moveForward(50);
counterWall++;
} while (counterWall < 9);
counter++;
}
waitKey();
}
edit: thanks everyone for the advice! I was fully intending to use a nested loop in the end(and did use one, so no lost points there!) and was able to realize there was nothing stopping me from looping the bricks like a snake. I had to turn the assignment in before I could try any of the changes you guys offered, but I'll be sure to keep them in mind for future assignments!
and here's a link to the picture of the final product, I've never been happier to see a brick wall in my life
Brick Wall Picture
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I'm programming a Breakout game in C++. I'm having a HUGE problem that's preventing me from giving the game multi-ball functionality. I think it has something to do with the destructor. Have a look:
for loop for the balls (Driver.cpp):
for (Ball& b : balls) { // Loops over all balls
(...)
// Collision for when you miss
if (b.getYPos() > HEIGHT) { // If the ball falls below the defined height of the screen
balls.erase(balls.begin() + b.getID()); // Wipe the ball out of memory to make room (Troublesome line)
Ball::addToID(-1); // Shift the ball ID to assign to the next ball back one
(...)
}
And I get this error:
Debug Error!
Program: Breakout.exe
abort() has been called
(Press Retry to debug the application)
Do you know why this mysterious crash is happening? Or more importantly, a fix for it?
Here's a replicable piece of code to help:
Driver.cpp:
#include <vector>
#include <allegro5\allegro.h>
#include "Ball.h"
using namespace std;
vector<Ball> balls(0); // Pay attention to this line
const POS WIDTH = 1600, HEIGHT = 900;
int main {
while (running) {
if (al_key_down(&key, ALLEGRO_KEY_SPACE)) { // Spawn the ball
balls.push_back(Ball(WIDTH / 2, 500, 10, 10)); // Spawn the ball
balls[Ball::getIDtoAssign()].setYSpeed(5);
}
for (Ball& b : balls) { // Pay attention to this loop
b.draw(); // This line is what's crashing.
b.move();
(...)
// Collision for when you miss
balls.erase(
remove_if(balls.begin(), balls.end(),
[=](Ball& b) {
// Collision for when you miss
return b.getYPos() > HEIGHT; // If the ball falls below the defined height of the screen, wipe the ball out of memory to make room
}
),
balls.end()
);
}
}
}
}
return 0;
}
Ball.h:
#pragma once
#include <allegro5\allegro_primitives.h>
using namespace std;
class Ball {
public:
Ball();
Ball(float x, float y, float w, float h);
~Ball();
void draw();
void move();
float getYPos();
void setYSpeed(float set);
private:
float xPos; // Horizontal position
float yPos; // Vertical position (upside down)
float width; // Sprite width
float height; // Sprite height
float xSpeed; // Horizontal speed
float ySpeed; // Vertical speed (inverted)
}
Ball.cpp:
#include "Ball.h"
short Ball::ballIDtoAssign = 0;
Ball::Ball() {
this->xPos = 0;
this->yPos = 0;
this->width = 0;
this->height = 0;
this->xSpeed = 0;
this->ySpeed = 0;
}
Ball::Ball(float x, float y, float w, float h) {
this->xPos = x;
this->yPos = y;
this->width = w;
this->height = h;
this->xSpeed = 0;
this->ySpeed = 0;
}
Ball::~Ball() {
// Destructor
}
void Ball::draw() {
al_draw_filled_rectangle(xPos, yPos, xPos + width, yPos + height, al_map_rgb(0xFF, 0xFF, 0xFF));
}
void Ball::move() {
xPos += xSpeed;
yPos += ySpeed;
}
float Ball::getYPos() {
return yPos;
}
void Ball::setYSpeed(float set) {
ySpeed = set;
}
You cannot modify a container while you are iterating through it with a range-for loop. You don't have access to the iterator that the loop uses internally, and erase() will invalidate that iterator.
You can use the container's iterators manually, paying attention to the new iterator that erase() returns, eg:
for(auto iter = balls.begin(); iter != balls.end(); ) { // Loops over all balls
Ball& b = *iter:
...
// Collision for when you miss
if (b.getYPos() > HEIGHT) { // If the ball falls below the defined height of the screen
...
iter = balls.erase(iter); // Wipe the ball out of memory to make room
}
else {
++iter;
}
}
Alternatively, use the erase-remove idiom via std::remove_if() instead:
balls.erase(
std::remove_if(balls.begin(), balls.end(),
[=](Ball &b){
// Collision for when you miss
return b.getYPos() > HEIGHT; // If the ball falls below the defined height of the screen, wipe the ball out of memory to make room
}
),
balls.end()
);
UPDATE: now that you have posted more of your code, it is clear to see that you are trying to use ID numbers as indexes into the vector, but you are not implementing those IDs correctly, and they are completely unnecessary and should be eliminated.
The Ball::ballID member is never being assigned any value, so in this statement:
balls.erase(balls.begin() + b.getID()); // The troublesome line
Trying to erase() the result of balls.begin() + b.getID() causes undefined behavior since the iterator has an indeterminate value, thus you can end up trying to erase the wrong Ball object, or even an invalid Ball object (which is likely the root cause of your runtime crash).
Also, in this section of code:
balls.push_back(Ball(WIDTH / 2, 500, 10, 10)); // Spawn the ball
balls[Ball::getIDtoAssign()].setYSpeed(5);
Ball::addToID(1);
Since you want to access the Ball object you just pushed, that code can be simplified to this:
balls.back().setYSpeed(5);
And I already gave you code further above to show you how to remove balls from the vector without using IDs.
So, there is need for an ID system at all.
With that said, try something more like this:
Driver.cpp:
#include <vector>
...
#include "Ball.h"
using namespace std;
vector<Ball> balls;
const POS WIDTH = 1600, HEIGHT = 900;
int main {
...
while (running) {
...
if (input.type == ALLEGRO_EVENT_TIMER) { // Runs at 60FPS
...
if (al_key_down(&key, ALLEGRO_KEY_SPACE)) { // Spawn the ball
balls.push_back(Ball(WIDTH / 2, 500, 10, 10)); // Spawn the ball
balls.back().setYSpeed(5);
}
for (auto iter = balls.begin(); iter != balls.end(); ) {
Ball &b = *iter;
...
if (b.getYPos() > HEIGHT) { // Collision for when you miss
iter = balls.erase(iter);
}
else {
++iter;
}
}
/* alternatively:
for (Ball& b : balls) {
b.draw();
b.move();
}
balls.erase(
std::remove_if(balls.begin(), balls.end(),
[=](Ball &b){
// Collision for when you miss
return b.getYPos() > HEIGHT; // If the ball falls below the defined height of the screen, wipe the ball out of memory to make room
}
),
balls.end()
);
*/
}
}
return 0;
}
Ball.h:
#pragma once
...
class Ball {
public:
...
// NO ID METHODS!
private:
...
// NO ID MEMBERS!
}
Ball.cpp:
#include "Ball.h"
...
// NO ID MEMBER/METHODS!
OK, so I managed to figure out why the program crashes. It was because I had the erase-remove inside the for loop which can cause all sorts of problems.
I'm trying to make a first person shooter style camera for my project. Everything looks smooth if I'm moving forward or back, strafing left or right, or going diagonal... The problem is when I look around with the mouse while moving, the movements get really jittery. It is most prominent when I am strafing and turning with the mouse at the same time.
I'm convinced my problem is similar to this: http://en.sfml-dev.org/forums/index.php?topic=4833.msg31550#msg31550 , however I am using Gentoo Linux, not OSX.
It's quite likely that it's not SFML's fault though, and that I did something wrong, so I would like to get some feedback on my event handling code to see if there's a better way to get smooth mouse movements.
In case you don't want to read through the link I posted, the short of what I think is happening is the mouse movement velocity is being lost every frame when I set the mouse's position back to the center of the screen, which causes a quick visible jerk on screen. This is my going theory as I've tried changing other stuff around for 3 days now and nothing I do makes it less jerky. So I would like to know if anyone has a better way of handling the mouse movements, or whether you think the problem lies elsewhere.
An important note is I have enabled vsync which made a lot of other jitteriness and tearing go away, and I tried using a hard framerate limit like sf::Window::setFramerateLimit(60), but that didn't help at all.
Here is the event handler (which uses the SFML 2.0 realtime interfaces instead of an event loop), you can probably ignore the part related to jumping:
void Test_World::handle_events(float& time)
{
// camera stuff
_mouse_x_pos = sf::Mouse::getPosition(*_window).x;
_mouse_y_pos = sf::Mouse::getPosition(*_window).y;
std::cout << "mouse x: " << _mouse_x_pos << std::endl;
std::cout << "mouse y: " << _mouse_y_pos << std::endl;
_horizontal_angle += time * _mouse_speed * float(_resolution_width/2 - _mouse_x_pos);
_vertical_angle += time * _mouse_speed * float(_resolution_height/2 - _mouse_y_pos);
// clamp rotation angle between 0 - 2*PI
if (_horizontal_angle > 3.14f*2) _horizontal_angle = 0;
if (_horizontal_angle < 0) _horizontal_angle = 3.14f*2;
// clamp camera up/down values so we can't go upside down
if (_vertical_angle >= 3.14f/2.0f) _vertical_angle = 3.14f/2.0f;
if (_vertical_angle <= -3.14f/2.0f) _vertical_angle = -3.14f/2.0f;
std::cout << "horiz angle: " << _horizontal_angle << std::endl;
std::cout << "vert angle: " << _vertical_angle << std::endl;
_direction = glm::vec3( cos(_vertical_angle) * sin(_horizontal_angle),
sin(_vertical_angle),
cos(_vertical_angle) * cos(_horizontal_angle) );
_right = glm::vec3( sin(_horizontal_angle - 3.14f/2.0f),
0,
cos(_horizontal_angle - 3.14f/2.0f) );
_up = glm::cross( _right, _direction );
// keyboard: left, right, up, down
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left) || sf::Keyboard::isKeyPressed(sf::Keyboard::A))
{
if (_jumping)
{
_position -= _right * time * _speed * ((_jump_speed/2) + 0.1f);
}
else
{
_position -= _right * time * _speed;
}
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right) || sf::Keyboard::isKeyPressed(sf::Keyboard::D))
{
if (_jumping)
{
_position += _right * time * _speed * ((_jump_speed/2) + 0.1f);
}
else
{
_position += _right * time * _speed;
}
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up) || sf::Keyboard::isKeyPressed(sf::Keyboard::W))
{
glm::vec3 old_direction(_direction);
_direction.y = 0;
if (_jumping)
{
_position += _direction * time * _speed * ((_jump_speed/2) + 0.1f);
}
else
{
_position += _direction * time * _speed;
}
_direction = old_direction;
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down) || sf::Keyboard::isKeyPressed(sf::Keyboard::S))
{
glm::vec3 old_direction(_direction);
_direction.y = 0;
if (_jumping)
_position -= _direction * time * _speed * ((_jump_speed/2) + 0.1f);
else
_position -= _direction * time * _speed;
_direction = old_direction;
}
// keyboard: jump
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Space) || sf::Keyboard::isKeyPressed(sf::Keyboard::RControl))
{
// check if standing on something
if (_standing)
{
_standing = false;
_jumping = true;
}
}
// apply gravity if off the ground
if (_position.y > _main_character_height && !_jumping)
_position.y -= time * _speed * _global_gravity;
// if started jumping
else if (_position.y < _main_character_height + _jump_height - 3.0f && _jumping)
{
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Space) || sf::Keyboard::isKeyPressed(sf::Keyboard::RControl))
{
_position.y += time * _speed * _jump_speed;
}
else // if stopped jumping
{
_position += _direction * time * (_speed/(_jump_hang_time*2));
_jumping = false;
}
}
// if near the highest part of the jump
else if (_position.y <= _main_character_height + _jump_height && _jumping)
{
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Space) || sf::Keyboard::isKeyPressed(sf::Keyboard::RControl))
{
_position.y += time * _speed * (_jump_speed/_jump_hang_time);
}
else // if stopped jumping
{
_position += _direction * time * (_speed/(_jump_hang_time*2));
_jumping = false;
}
}
// if reached the highest part of the jump
else if (_position.y >= _main_character_height + _jump_height)
{
_position += _direction * time * (_speed/_jump_hang_time);
_jumping = false;
}
else if (_position.y <= _main_character_height)
{
_standing = true;
}
sf::Mouse::setPosition(_middle_of_window, *_window);
}
After the events, I am changing my _view_matrix like this:
_view_matrix = glm::lookAt( _position, _position+_direction, _up );
Then, I recalculate my _modelview_matrix and _modelviewprojection_matrix:
_modelview_matrix = _view_matrix * _model_matrix;
_modelviewprojection_matrix = _projection_matrix * _modelview_matrix;
After that I finally send the matrices to my shaders and draw the scene.
I am open to any sage wisdom/advice with regards to OpenGL3, SFML 2.0, and/or FPS-style camera handling, and please let me know if it would help to include more code (if you think the problem isn't in the event handling, for example). Thanks in advance for the help!
Edit: I still haven't solved this problem, and FYI it doesn't look like the framerate is dropping at all during the shaky movements...
If I was you I would hide the mouse using this tutorial and then only move the mouseposition when it got to the edge of the screen moving it to the opposite side so it can continue in that direction un-impeded. May not be the best solution, but I'm pretty sure it'll fix your issue.
... another idea is to do some remembering and reckoning as to what they are doing and not use the position data itself, but simply use the position data to guide the reckoning (i.e. use physics to control it instead of the raw data).
Just my thoughts, hope they help^^
I was reading this topic and I decided to give it a shot. To my astonishment it really seemed easier than what I am making it I guess. I have some confusion about the "DesiredPos" variable. Well at least in my implementation. I am trying to move a window around constantly and have it react like a ball when it hits the monitors edges. Like the ball in the game Pong. I have made programs like this that move the mouse, But I can't seem to get my head around this one.
This is what I have so far, I have limited experience when it comes to a lot of functions in the Windows API. Keep in mind this is a hardcore rough draft.
EDIT
I haven't implemented any of the collision detection yet I just wanted to get the moving portion working.
#include <windows.h>
#include <math.h>
int newX(int oldx);
int newY(int oldy);
double SmoothMoveELX(double x);
int main()
{
int lengthInMs = 10*1000;
HWND notepad = FindWindow("Notepad",NULL);
RECT window;
SetTimer(
notepad,
NULL,
30,
(TIMERPROC)NULL
);
int startTime = GetTickCount();
int pos = elap / lengthInMs;
while(1)
{
RECT window;
GetWindowRect(notepad,&window);
int elap = (GetTickCount() - startTime);
if(elap >= lengthInMs)
{
int NEWX = NewX(window.x);
int NEWY = NewY(window.y);
MoveWindow(
notepad,
NEWX,
NEWY,
100,
100,
TRUE
);
}
}
}
int NewX(int oldx)
{
int newx = oldx*(1-SmoothMoveELX(pos))
+ 10 *SmoothMoveELX(pos));
return newx;
}
int newY(int oldy)
{
int newy = oldy*(1-SmoothMoveELX(pos))
+ 10 *SmoothMoveELX(pos));
return newy;
}
double SmoothMoveELX(double x)
{
double PI = Atan(1) * 4;
return ((cos(1 - x) * PI + 1) /2 )
}
My advice is to take a look on the "verlet integration". It is a quite easy way to simulate basic mechanics. Google for it and you'll find many examples for it, including collision detection and friction. On the long run this will give you more natrual results then estimating the velocity or the new position with a sine function.