I'm trying to move the user mouse using mouse_event function in WinAPI. This is my code:
while (LeftMouseDown)
{
POINT cursorPos;
GetCursorPos(&cursorPos);
//X Axis And Y Axis is DWORD Array
mouse_event(MOUSEEVENTF_MOVE, xaxis[iCount], yaxis[iCount], 0, 0);
iCount++;
Sleep(200);
}
It's working good but the problem is that I want the code smooth movement, because the function teleports the cursor instantly and I don't want that, I want it to be smooth transition or something like that.
From what it looks like, you are trying to move across a path of points in a smooth manner.
If so, then you are going to have to interpolate along that path via time.
Essentially, the idea is that you first obtain the total length of the path. Then as you are updating time you obtain a total distance via the total duration and the elapsed amount of time. Finally, you find the two points where the obtained distance is somewhere in the middle. Then you simply interpolate along those two points to get a relatively accurate point.
With this class you can pass the points for the path and a a duration to specify how long you would like to be moving along the path for. Then you would simply update it via time intervals.
Mover.h
#include <chrono>
#include <vector>
#ifndef MOVER_H
#define MOVER_H
struct Point {
int x, y;
Point(int x_, int y_)
: x(x_), y(y_) {
}
Point() : Point(0, 0) {
}
};
class Mover {
public:
struct PointData {
float total;
float distance;
Point p1;
Point p2;
PointData()
: total(0.f),
distance(0.f) {
}
PointData(float total, float distance, Point p1, Point p2)
: total(total),
distance(distance),
p1(p1),
p2(p2) {
}
};
using TimePoint = std::chrono::microseconds;
private:
std::vector<Point> m_points;
std::vector<PointData> m_distances;
TimePoint m_duration;
TimePoint m_elapsed;
float m_length;
public:
Mover(std::initializer_list<Point> points, TimePoint duration = std::chrono::microseconds(2000000));
template<typename iter_t>
Mover(iter_t begin, iter_t end, TimePoint duration = std::chrono::microseconds(2000000))
: m_points(begin, end),
m_duration(duration),
m_elapsed(std::chrono::milliseconds(0)) {
updateLength();
}
Mover(const Mover&) = default;
Mover& operator=(const Mover&) = default;
Point update(TimePoint delta);
bool isComplete() const;
void setDuration(TimePoint duration);
TimePoint getDuration() const;
TimePoint getElapsed() const;
private:
void updateLength();
};
#endif // MOVER_H
Mover.cpp
#include "Mover.h"
#include <algorithm>
#include <cmath>
Mover::Mover(std::initializer_list<Point> points, TimePoint duration)
: Mover(points.begin(), points.end(), duration)
{
}
Point Mover::update(TimePoint delta)
{
const auto comparison = [](float left, const PointData& right) {
return left < right.total;
};
m_elapsed = std::min(m_elapsed + delta, m_duration);
const float length = (static_cast<float>(m_elapsed.count()) / static_cast<float>(m_duration.count())) * m_length;
auto& data = *std::prev(std::upper_bound(m_distances.begin(), m_distances.end(), length, comparison));
const float percent = (length - data.total) / data.distance;
Point point(data.p1.x + percent * (data.p2.x - data.p1.x), data.p1.y + percent * (data.p2.y - data.p1.y));
return point;
}
bool Mover::isComplete() const
{
return m_duration == m_elapsed;
}
void Mover::setDuration(TimePoint duration)
{
m_duration = duration;
}
Mover::TimePoint Mover::getDuration() const
{
return m_duration;
}
Mover::TimePoint Mover::getElapsed() const
{
return m_elapsed;
}
void Mover::updateLength()
{
auto distance = [](float x1, float y1, float x2, float y2) -> float{
return std::sqrt(((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)));
};
float length = 0.f;
for (std::size_t index = 0; (index + 1) < m_points.size(); ++index) {
const float dist = distance(m_points[index].x, m_points[index].y, m_points[index + 1].x, m_points[index + 1].y);
m_distances.emplace_back(length, dist, m_points[index], m_points[index + 1]);
length += dist;
}
m_length = length;
}
Example
#include <iostream>
#include "Mover.h"
int main() {
std::vector<Point> points{ { 0, 0 }, { 100, 100 } };
Mover move(points.begin(), points.end());
auto t1 = std::chrono::steady_clock::now();
while (!move.isComplete()) {
auto t2 = std::chrono::steady_clock::now();
auto point = move.update(std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1));
std::cout << point.x << ' ' << point.y;
t1 = t2;
}
}
It's worth mentioning that in order to use this you are going to have to keep track of the time in order to update the mover. So it's probably worth implementing a Clock class or something to keep track of the time for you.
Also, if you want to move along the path relative to the current cursor position, then you would have to simply add the cursor position to the active path point.
I know this is very late but I might as well answer it.
while doing golang I used this library called robot.go and over there they have a function that does the smooth input. So if you want you can use that as a reference.
https://github.com/go-vgo/robotgo/blob/master/mouse/mouse_c.h
looking at your code your mouse will jump pixels every 200 ms.
while (LeftMouseDown)
{
POINT cursorPos;
GetCursorPos(&cursorPos);
//X Axis And Y Axis is DWORD Array
int i;
for (i = 0; i < 20; i++)
{
mouse_event(MOUSEEVENTF_MOVE, (xaxis[icount]-cursorPos.x)/20, (yaxis[icount]-cursorPos.y)/20, 0, 0);
iCount++;
Sleep(10);
}
}
Related
I'm trying to code metaballs in C++/SFML, my program works just fine in a single thread. I tried to write an MRE to find the problem and here's what I got:
main.cpp
// main
#include <iostream>
#include "threader.h"
float func(float x, float y, float a, float b, float r) {
return 1.f / sqrt((x - a)*(x - a) + (y - b)*(x - b));
}
int main () {
sf::RenderWindow window(sf::VideoMode(2800, 1800), "");
window.setFramerateLimit(20);
sf::Event event{};
threader tf(window);
while (window.isOpen()) {
while (window.pollEvent(event)) {
switch (event.type) {
case sf::Event::Closed: {
window.close();
}
}
}
window.clear();
tf.parallel(func);
window.display();
}
}
threader.h
//threader_H
#pragma once
#include <array>
#include <thread>
#include <cmath>
#include <functional>
#include <SFML/Graphics.hpp>
class threader {
public:
int threadCount = 4;
std::array<std::thread, 4> threads;
sf::RenderWindow& window;
public:
explicit threader(sf::RenderWindow& w) : window(w) {};
void strip(int start, int end, const std::function<float(float, float, float, float, float)>& func);
void parallel(const std::function<float(float, float, float, float, float)>& func);
};
threader.cpp
// threader_CPP
#include "threader.h"
#include <iostream>
void threader::strip (int start, int end, const std::function<float (float, float, float, float, float)> &func) {
for (int X = start; X < end; X += 10) {
for (int Y = 0; Y < window.getSize().y; Y += 10) {
auto x = static_cast<float>(X);
auto y = static_cast<float>(Y);
x = x / 2800.f * 4 + 0 - 4 / 2.f;
y = -((1800.f - y) / 1800 * 4 + 0 - 4 / 2.f);
if (func(x, y, 1, 2, 3) > 1) {
sf::CircleShape circle(20);
circle.setPointCount(3);
circle.setFillColor(sf::Color::Cyan);
circle.setPosition(X, Y);
window.draw(circle);
}
}
}
}
void threader::parallel (const std::function<float (float, float, float, float, float)> &func) {
int start = 0;
int end = window.getSize().x / threadCount;
for (auto& t : threads) {
t = std::thread(&threader::strip, this, start, end, func);
start = end;
end += window.getSize().x / threadCount;
}
for (auto& t : threads) {
t.join();
}
}
Now for the explanation. threader is a class which has two methods: strip that calculates a function for a given strip of the window and parallel that creates threads to separately calculate my function for every strip. This code doesn't work:
But here's the catch: if I adjust the function void func(...) in main to return 1.f / sqrt((x - a) + (y - b)), everything works just fine. What is happening? How a simple calculation can cause a segfault? help please...
EDIT 1: Written in CLion, C++ 20.
EDIT 2: If anything here makes sense, please explain it to me.
Rather than try to draw to the window on multiple threads, I would instead use std algorithms to filter the points to draw circles, and draw them all on the main thread.
std::vector<std::pair<int, int>> getPoints(const sf::RenderWindow& window) {
std::vector<std::pair<int, int>> points;
for (int X = 0; X < window.getSize().x; X += 10) {
for (int Y = 0; Y < window.getSize().y; Y += 10) {
points.emplace_back(X, Y);
}
}
return points;
}
template<typename F>
auto filter(F f) {
return [f](const std::pair<int, int> & point) {
auto x = static_cast<float>(point.first);
auto y = static_cast<float>(point.second);
x = x / 2800.f * 4 + 0 - 4 / 2.f;
y = -((1800.f - y) / 1800 * 4 + 0 - 4 / 2.f);
return (func(x, y, 1, 2, 3) > 1);
}
}
sf::CircleShape toCircle(int X, int Y) {
sf::CircleShape circle(20);
circle.setPointCount(3);
circle.setFillColor(sf::Color::Cyan);
circle.setPosition(X, Y);
return circle;
}
template <typename F>
void drawCircles(sf::RenderWindow& window, F f) {
auto points = getPoints(window);
auto end = std::remove_if(std::execution::par, points.begin(), points.end(), filter(f));
points.erase(end, points.end());
for (auto & [X, Y] : points) {
window.draw(toCircle(X, Y));
}
}
float func(float x, float y, float a, float b, float r) {
return 1.f / sqrt((x - a)*(x - a) + (y - b)*(x - b));
}
int main () {
sf::RenderWindow window(sf::VideoMode(2800, 1800), "");
window.setFramerateLimit(20);
sf::Event event{};
threader tf(window);
while (window.isOpen()) {
while (window.pollEvent(event)) {
switch (event.type) {
case sf::Event::Closed: {
window.close();
}
}
}
window.clear();
drawCircles(window, func);
window.display();
}
}
There is a problem with trying to render from multiple threads without properly switching GL contexts.
Since you are doing this on the CPU, here are some options:
Make multiple sf::RenderTexture objects, render to each one of them in a separate thread (don't forget to call display() at the end), then draw them on the main thread in some sprites. (harder and not sure it is the way to go, but I don't know what you want to do in the end)
Make multiple sf::Image objects, render to each one of them in a separate thread, then draw them on the main thread in some sprites.
Make just one sf::Image object, each thread renders in a separate area of the image, then draw the image on the main thread in some sprite.
options 2 & 3 make it more easy to work with at a pixel level, also faster. Make sure you traverse the image in a cache friendly way (line by line most likely)
I would go with 2 or 3 depending on how you think it's better for your application.
Also, use sf::Transform for the transformation from screen space (Image space) to world space where the metaballs live.
https://www.sfml-dev.org/documentation/2.5.1/classsf_1_1Image.php
https://www.sfml-dev.org/documentation/2.5.1/classsf_1_1Transform.php#ab42a0bb7a252c6d221004f6372ce5fdc
I am still struggling to realize what I want to do.
My code shall take user-defined segments (e.g. either a line, a circle, or whatever geometric segment definition I will implement) and chain them together in a vector. However, the order of segment type ("line", "circle",...) is user-defined and may hence vary from execution to execution.
Before I go on: Each segment has different input data needed for its own creation (e.g. a line has no radius, only starting and ending point).
My preferred approach would be to
read user input and identify order of segments
create each segment
Feed these to a function (e.g. member function/method for a class implementing the contour).
This function creates the contour, e.g. by implementing a vector.
My current test code has a hard-coded segment sequence but the trick that I want to achieve is that the order (and number) of segments is not hard-coded. Unfortunately I cannot figure out how.
Here's the code:
#include <iostream>
#include <vector>
struct point
{
double x;
double y;
};
class segment
{
public:
segment()
{
P1.x = 0;
P1.y = 0;
P2.x = 0;
P2.y = 0;
};
virtual ~segment() {};
virtual double get_radius() { return 0; };
virtual double get_length() { return 0; };
virtual double get_angle() { return 0; };
int segment_id = 0;
protected:
point P1;
point P2;
};
class Line : public segment
{
public:
Line() {};
Line(const point pt1, const point pt2)
{
P1.x = pt1.x;
P1.y = pt1.y;
P2.x = pt2.x;
P2.y = pt2.y;
segment_id = 1;
};
~Line() {};
double get_length() { return calc_length(); };
double get_angle() { return calc_angle(); };
private:
double calc_length()
{
// calculate length (here: dummy value)
return 1;
}
double calc_angle()
{
// calculate angle (here: dummy value)
return 0.5;
}
double length = 0;
double angle = 0;
}
;
class circle : public segment
{
public:
circle()
{
center.x = 0;
center.y = 0;
};
circle(const double r, const point c)
{
radius = r;
center.x = c.x;
center.y = c.y;
segment_id = 2;
};
~circle() {};
double get_radius() { return radius; };
point get_center() { return center; };
double get_length() { return 3.14 * radius; }; //returns circumference
private:
double radius = 0;
point center;
};
//-------------------------------------------------------
int main()
{
int nbr = 5;
point start;
start.x = 1;
start.y = 2;
point end;
end.x = 3;
end.y = 4;
point c;
c.x = 0;
c.y = 0;
double r = 9;
auto anotherCircle = std::make_unique<circle>(r, c);
auto anotherLine = std::make_unique<Line>(start, end);
std::unique_ptr<circle> yet_anotherCircle;
circle* myCircle = new circle(r, c);
Line* myLine = new Line(start, end);
//VERSION 1: Does not compile. I get an exception in <memory> line 1762 when trying to delete _Ptr
//std::vector<std::unique_ptr<segment>> v1;
//v1.emplace_back(anotherCircle);
//v1.emplace_back(anotherLine);
//std::cout << v1[0]->get_radius() << std::endl;
//v1.emplace_back(myLine);
//std::cout << v1[1]->segment_id << std::endl;
//VERSION 2: Compiles
std::vector<std::unique_ptr<segment>> v2;
v2.emplace_back(std::make_unique<circle>(r, c));
v2.emplace_back(std::make_unique<Line>(start, end));
}
The straight forward way that I imagine but that does not seem to work would require version 1 to work. I could then probably use template objects that I feed into the vector. Unfortunately this is not the way to go and I have not the slightest idea how to approach this. It would be awesome if somebody could help me here! Thanks!
You need to move items in vector, as your items are no copyable:
v1.emplace_back(std::move(anotherCircle));
I have another problem that I have no idea how to solve. Maybe somebody can help me.
What I want to do:
I have a vector that shall take elements of various class types. In my example code I have two classes (Line, circle) that are both derived from a virtual class segment.
My code shall chain several circle or Line elements and put them in the vector. Each element may be different from the other (different radii, different starting and ending points, etc) and the sequence of elements shall vary from execution to execution. That is for instance for the first execution I have a circle with radius 2 followed by another circle of radius 1, followed by a Line of length 4 and for the second execution I have a Line of length 1 followed by another Line of Length 5 in a different direction, followed by a circle of radius 0.5.
I've already learned how to compose the vector such that it can contain different types but as of now the sequence and definition of each element is hard-coded. Now I want to make this flexible (in the end the sequence and definition shall be file-driven). For this I attempt to implement a template function that takes whatever element is fed into it and adds it to the vector. The current definition also takes the vector as input but I may end up to define this function as a method for the vector.
Unfortunately I cannot figure out a way how to do it that works. I understand that I cannot copy a unique_ptr so I tried with the std::move() method but doesn't work. I get an C2664 error message of the xmemory module in line 671 saying that I cannot convert argument 1 in T2 into a std::nullptr_t.
Can somebody help me here? That'll be so awesome!
Here's my example code that implements the basic idea for my code:
#include <iostream>
#include <vector>
#include <variant>
struct point
{
double x;
double y;
};
class segment
{
public:
segment()
{
P1.x = 0;
P1.y = 0;
P2.x = 0;
P2.y = 0;
};
virtual ~segment() {};
virtual double get_radius() { return 0; };
virtual double get_length() { return 0; };
virtual double get_angle() { return 0; };
int segment_id = 0;
protected:
point P1;
point P2;
};
class Line : public segment
{
public:
Line() {};
Line(const point pt1, const point pt2)
{
P1.x = pt1.x;
P1.y = pt1.y;
P2.x = pt2.x;
P2.y = pt2.y;
segment_id = 1;
};
~Line() {};
double get_length() { return calc_length(); };
double get_angle() { return calc_angle(); };
private:
double calc_length()
{
// calculate length (here: dummy value)
return 1;
}
double calc_angle()
{
// calculate angle (here: dummy value)
return 0.5;
}
double length = 0;
double angle = 0;
}
;
class circle : public segment
{
public:
circle()
{
center.x = 0;
center.y = 0;
};
circle(const double r, const point c)
{
radius = r;
center.x = c.x;
center.y = c.y;
segment_id = 2;
};
~circle() {};
double get_radius() { return radius; };
point get_center() { return center; };
double get_length() { return 3.14 * radius; }; //returns circumference
private:
double radius = 0;
point center;
};
//-------------------------------------------------------
//T1: class type "segment", T2: class object Line or circle
template<typename T1, typename T2>
inline void add_segment(T1 v, T2 line_or_circle)
{
v.emplace_back(line_or_circle);
}
//-------------------------------------------------------
int main()
{
int nbr = 5;
point start;
start.x = 1;
start.y = 2;
point end;
end.x = 3;
end.y = 4;
point c;
c.x = 0;
c.y = 0;
double r = 9;
auto anotherCircle = std::make_unique<circle>(r, c);
auto anotherLine = std::make_unique<Line>(start, end);
circle myCircle(r, c);
//VERSION 1: Does now compile.
std::vector<std::unique_ptr<segment>> v1;
v1.emplace_back(std::move(anotherCircle));
v1.emplace_back(std::move(anotherLine));
std::cout << v1[0]->get_radius() << std::endl;
std::cout << v1[1]->segment_id << std::endl;
//VERSION 2: Compiles
std::vector<std::unique_ptr<segment>> v2;
v2.emplace_back(std::make_unique<circle>(r, c));
v2.emplace_back(std::make_unique<Line>(start, end));
//=================================================================
//now I want to implement this as a function call
//=================================================================
std::vector<std::unique_ptr<segment>> v3;
//VERSION 5:
auto myLine2 = std::make_unique<Line>(start, end);
add_segment(v3, std::move(myLine2)); //shall add object of class Line or circle (derived from virtual segment class, see above) to vector v3. In this example a Line but might be a circle
}
Your function add_segment is taking the vector by value. This fails to compile because the vector is uncopyable, as unique pointers are uncopyable. Even if you used a copyable pointer type, it would be a pointless method as the copy is destroyed at the end of the function.
You will also need to move the line_or_circle parameter in the body of add_segment.
template<typename T1, typename T2>
inline void add_segment(T1 & v, T2 line_or_circle)
{
v.emplace_back(std::move(line_or_circle));
}
I'm trying to implement collision detection in sfml using the separating axis theorem but my function to get the min translation vector (getMtv()) is always returning that there is a collision (MTV::IsValid()). I was following a tutorial here
but I can't see where I went wrong.
#include <iostream>
#include <math.h>
#include <SFML/Graphics.hpp>
#include <gtest/gtest.h>
typedef sf::Vector2f Vector2;
typedef sf::Vector2f Axis;
typedef sf::Vector2f Projection;
typedef std::vector<Axis> AxesVec;
class MTV
{
private:
bool _valid;
Axis _axis;
float _overlap;
public:
MTV(Axis axis, float overlap, bool valid)
{
_valid = valid;
_overlap = overlap;
_axis = axis;
}
bool IsValid() const
{
return _valid;
}
};
Vector2 perpendicular(Vector2 v)
{
return Vector2(v.y, -v.x);
}
float dot(Vector2 vec1, Vector2 vec2)
{
return (vec1.x * vec2.x) + (vec1.y * vec2.y);
}
float magnitude(Vector2 v)
{
return std::sqrt(dot(v,v));
}
class Polygon : public sf::ConvexShape
{
public:
const AxesVec& GetAxes() const
{
return axes;
}
AxesVec axes;
void generateAxes()
{
for (int i = 0; i < getPointCount(); i++)
{
// get the current vertex
Vector2 p1 = getPoint(i); //shape.vertices[i];
// get the next vertex
Vector2 p2 = getPoint(i + 1 == getPointCount() ? 0 : i + 1);
// subtract the two to get the edge vector
Vector2 edge = p1 - p2;
// get either perpendicular vector
Vector2 normal = perpendicular(edge);
// the perp method is just (x, y) => (-y, x) or (y, -x)
axes.push_back(normal / magnitude(normal));
}
};
float cross(Vector2 vec1, Vector2 vec2)
{
return (vec1.x * vec2.y) - (vec1.y * vec2.x);
}
Vector2 project(Polygon p, Axis axis)
{
float min = dot(axis, p.getPoint(0)); //axis.dot(shape.vertices[0]);
float max = min;
for (int i = 1; i < p.getPointCount(); i++)
{
// NOTE: the axis must be normalized to get accurate projections
float prj = dot(axis, p.getPoint(i));//axis.dot(shape.vertices[i]);
if (prj < min)
{
min = prj;
}
else if (prj > max)
{
max = prj;
}
}
//Projection proj = new Projection(min, max);
return Projection(min, max);
}
class Collison
{
private:
Vector2 mtv;
Polygon a;
Polygon b;
};
bool overlap(Projection a, Projection b)
{
// x = min & y = max
return !(a.x > b.y || a.x > b.y);
}
float getOverlap(Projection a, Projection b)
{
// x = min & y = max
return (a.y < b.y) ? a.y - b.x : b.y - a.x;
}
MTV getMtv(Polygon a, Polygon b)
{
float overlapMax = std::numeric_limits<float>::infinity();// really large value;
float Overlap;
Axis smallest;// = null;
AxesVec axesA = a.GetAxes();
AxesVec axesB = b.GetAxes();
// loop over the axes1
for (auto&& axis : axesA) //for (int i = 0; i < axes1.length; i++)
{
//Axis axis = axes1[i];
// project both shapes onto the axis
Projection pA = project(a, axis);
Projection pB = project(b, axis);
// do the projections overlap?
if (!overlap(pA, pB)) //(!p1.overlap(p2))
{
// then we can guarantee that the shapes do not overlap
return MTV(smallest, 0, false);
}
else
{
// get the overlap
float o = getOverlap(pA, pB); //p1.getOverlap(p2);
// check for minimum
if (o < overlapMax)
{
// then set this one as the smallest
Overlap = o;
smallest = axis;
}
}
}
for (auto&& axis : axesB) //for (int i = 0; i < axes1.length; i++)
{
//Axis axis = axes1[i];
// project both shapes onto the axis
Projection pA = project(a, axis);
Projection pB = project(b, axis);
// do the projections overlap?
if (!overlap(pA, pB)) //(!p1.overlap(p2))
{
// then we can guarantee that the shapes do not overlap
return MTV(smallest, 0, false);
}
else
{
// get the overlap
double o = getOverlap(pA, pB); //p1.getOverlap(p2);
// check for minimum
if (o < overlapMax)
{
// then set this one as the smallest
Overlap = o;
smallest = axis;
}
}
}
//MTV mtv = new MTV(smallest, overlap);
// if we get here then we know that every axis had overlap on it
// so we can guarantee an intersection
return MTV(smallest, Overlap, true);
}
int main(int argc, char **argv)
{
Polygon polygon;
polygon.setPointCount(3);
polygon.setPoint(0, sf::Vector2f(500, 100));
polygon.setPoint(1, sf::Vector2f(250, 500));
polygon.setPoint(2, sf::Vector2f(750, 500));
polygon.setFillColor(sf::Color::Red);
polygon.generateAxes();
Polygon polygon2;
polygon2.setPointCount(3);
polygon2.setPoint(0, sf::Vector2f(100, 0));
polygon2.setPoint(1, sf::Vector2f(50, 150));
polygon2.setPoint(2, sf::Vector2f(150, 150));
polygon2.generateAxes();
//polygon2.setPoint(0, sf::Vector2f(100, 0));
//polygon2.setPoint(1, sf::Vector2f(500, 150));
//polygon2.setPoint(2, sf::Vector2f(250, 150));
polygon2.setFillColor(sf::Color::Green);
sf::RenderWindow window(sf::VideoMode(800, 600), "My window");
// 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();
}
// clear the window with black color
window.clear(sf::Color::Black);
// draw everything here...
window.draw(polygon);
window.draw(polygon2);
std::cout << getMtv(polygon, polygon2).IsValid() << std::endl;
// end the current frame
window.display();
}
return 0;
}
I am doing my Object oriented programming assignment in which I am asked to create a game of catching numbers for children so that during their enjoyment they also learn counting numbers.
In here , I am supposed to create a Point class and an x-y coordinate. In here , I have to create a shift function which takes P (point object as a parameter). This function shift the first point when user presses key i.e arrow keys.
The problem is I am confused about what are the actual keywords use for arrow keys (like move UP, DOWN, LEFT, RIGHT) in c++ like we use in normal games to move an object or a person! ???
Here below is my code!
Class Point.h
#ifndef POINT_H
#define POINT_H
class Point
{
public:
Point(); // Default Constructor
Point(double, double, int); // Three argument constructor
void initialize(double, double, int);
void shift(Point p); // Shift the first point when user press keys
void setValue(int value);
int getValue() const;
void setX();
double getX() const;
void setY();
double gety() const;
void AddPointValue(Point p2); /*This function add the TWO points value
void displayPoint(); //This will use to display value of point
bool checkCoordinates();
bool checkTime(); // Check time remaining
private:
double x;
double y;
int value;
};
#endif
Implementation File
#include <iostream>
#include <windows.h>
#include "point.h"
using namespace std;
Point::Point() // Default Constructor
{
x = 0;
y = 0;
value = 0;
}
Point::Point(double x1, double y1, int value1){ // Three argument constructor
x = x1;
y = y1;
value = value1;
}
void Point::initialize(double init_x, double init_y, int init_value)
{
x = init_x;
y = init_y;
value = init_value;
}
void Point::shift(Point p){
if(p == VK_LEFT)
{
}else if(p == VK_RIGHT)
{
}else if(p == VK_UP)
{
}else if(p == VK_DOWN)
{
}
}
Its giving me an error right now that no match for an operator==(Operand type 'point' and 'int')
The issue with point and int is because you're trying to compare a 2d coordinate against an ASCII value (VK_*), change that part the following and it should be easier to maintain:
Point Point::shift(Point p, int keyPress)
{
Point maxSize = new Point();
Point minSize = new Point();
maxSize.x=80;
maxSize.y=40;
// Assuming a coordinate system of 0,0 (x,y) at top left of the display
switch (keyPress)
{
case (VK_LEFT): // increment the x coord by 1 to go left
p.x += 1;
if (p.x < minSize.x) p.x = minSize.x;
break;
case (VK_RIGHT): // decrement the x coord by 1 to go right
p.x -= 1;
if (p.x > maxize.x) p.x = maxSize.x;
break;
case (VK_UP): // decrement the y coord by 1 to go up
p.y -= 1;
if (p.y < minSize.y) p.y = minSize.y;
break;
case (VK_DOWN): // increment the y coord by 1 to go down
p.y += 1;
if (p.y > maxize.y) p.y = maxSize.y;
break;
}
return p;
}
you will also have to check that x and y are never smaller than 0 as that would take them off the display/cause an exception depending on how you structure the code and play area.
Hope this helps for your movement issues, but let me know if you need more info:)