I'm sorry if question title was unclear, but with my cheap english, I cant find a way to ask it clearly.
But I can explain it in long way.
So I have realized if I design my world(and with world, I mean ENTIRE game, it will be one level) 10.000x10.000... it will be very enough, other than few another sprite(and I mean like 4 or 5 with maximum of 50x50, nothing big.)
So I thought, why dont I make my entire map as 10.000x10.000(or lets say tons of 512x512) picture ?
But I have one question, there is few things you can "interact". they will(with they, I mean the stuff that is in my "world.jpg") be always stay at same place, but player(which is actually a sprite as you know) will move, therefore my 10.000x10.000 will "move".
So look at picture below, there is black dot which is "player" and red dot, which is lets say, a door.
and world is always centered to black dot unless he goes to end of the world. as you can see, (look at picture part 1 and part 2) when he moves a little bit to east, red dot looks moved. but I just moved my 10.000x10.000 image. Thats what I meant with the stuff on 10kx10k pic will move.
Anyway, but as you can see in last part of pic, when he goes near red dot, I want to my "action"
How to do it ?
-part below is not really related to main question
Is it useful to use 10kx10 pic instead of another sprites appearing on world when he moves ? but If I want to do that, not just I will check if he is nearby, but I will also check his point to realize if I should or shouldnt show him sprite.
Will it be more useful if I show my stuff when he comes to coordinates I want, or is using one big picture is OK ?
Thanks.
I would suggest a structure of the map somewhat like this..
public class Map
{
public MapPoint[,] mapPoints; //the map
public Player player; //the player/user object
public Vector2 DrawHeroPosition;
//where at the screen the player is going to be drawn
public Vector2 RangeStart;
//what part of the map who is going to be drawn
public int SizeX; //number of mapPoints the screen can contain at one time
public int SizeY; //number of mapPoints the screen can contain at one time
//MapPoint represents a specific 512x512 point (mapPoint) its position at
//the map but also includes the sprite that is going to be drawn and objects
//that the player can interact with at that place (like the door)
//the player object includes reference to where in the world it is place
public Map(ContentManager theContentManager, int x, int y)
{
MapSizeX = x;
MapSizeY = y;
int ScreenSizeX = 9;
int ScreenSizeY = 9;
mapPoints = new MapPoint[MapSizeX , MapSizeY];
//ad code for generating/creating map...
//important that you store the MapPoints position inside each mapPoint
player = new Player(mapPoints[0,0]); //crate a player who knows where he is
}
public void Update()
{
//in the update method you do a lot of things like movement and so
//set what part of the map the game should draw if the game for example
//can show 9x9 512points at a single time
//give range value from the players position
RangeStart.X = player.PositionX;
//test if the maps position is in the left corner of the map
//if it is draw the map from the start..(RangeStart.X = 0)
if (player.PositionX - (ScreenSizeX / 2) < 0) { RangeStart.X = 0; }
//if not draw the hero in the mitle of the screen
else
{
RangeStart.X = player.PositionX - (ScreenSizeX / 2);
}
//if the hero is in the right corer, fix his position
while (RangeStart.X + ScreenSizeX > MapSizeX)
{
RangeStart.X--;
}
//the same thing for the Y axle
RangeStart.Y = player.PositionY;
if (player.PositionY - (ScreenSizeY / 2) < 0) { RangeStart.Y = 0; }
else
{
RangeStart.Y = player.PositionY - (ScreenSizeY / 2);
}
while (RangeStart.Y + ScreenSizeY > MapSizeY)
{
RangeStart.Y--;
}
//time to set the position of the hero...
//he works like the opposite of the range, if you move what part of the map
//you draw you dont change the heros draw position, if you dont move the range
//you have to move the hero to create the illusion of "moment"
//if you are in the left part you have to move the heros draw position..
if (player.PositionX - (ScreenSizeX / 2) < 0)
{ DrawHeroPosition.X = player.PositionX; }
//if you are in the right part
else if (player.PositionX+1 > MapSizeX - (ScreenSizeX / 2))
{
DrawHeroPosition.X = player.PositionX - (MapSizeX - ScreenSizeX);
}
//if you aint in a corner, just place the hero in the middle of the map
else
{
DrawHeroPosition.X = (ScreenSizeX / 2);
}
//the same thing for Y
if (player.PositionY - (ScreenSizeY / 2) < 0)
{ DrawHeroPosition.Y = player.PositionY; }
else if (player.PositionY+1 > MapSizeY - (ScreenSizeY / 2))
{
DrawHeroPosition.Y = player.PositionY - (MapSizeY - ScreenSizeY);
}
else
{
DrawHeroPosition.Y = (ScreenSizeY / 2);
}
}
public void Draw()
{
int x = (int)RangeStart.X;
int y = (int)RangeStart.Y;
for(int counterX = 0; x < ((MapSizeX)); x++, counterX++)
{
for (int counterY = 0; y < (MapSizeY); y++, counterY++)
{
if (mapPoints[x, y] != null)
{
mapPoints[x, y].Draw(spriteBatch, mapPoints[counterX,counterY].positonInMatrix);
//mapPoints[counterX,counterY] = where to draw
//mapPoints[x, y] = what to draw
}
}
y = (int)RangeStart.Y;
}
}
}
how i draw inside the MapPoint Class...
public void Draw(SpriteBatch theSpriteBatch, Vector2 positonOnScreen)
{
positonOnScreen = new Vector2(positonOnScreen.X * base.Scale * 16,
positonOnScreen.Y * base.Scale * 16);
//base.Scale is just a variable for have the ability to zoom in/out
//16 represents the original size of the picture (16x16 pixels)
theSpriteBatch.Draw(mSpriteTexture, new Rectangle((int)positonOnScreen.X,
(int)(positonOnScreen.Y), 64, 64),new Rectangle(0, 0, 16, 16), Color.White);
}
If you are asking for collision detection within a radius of your red dot. You can simply use the following test (pseudocode, I don't write C# :-)
if( (player.GetPosition() - point.GetPosition()).length() < radius )
{ /* Do code here */ }
This will detect if your player is within a certain radius of your dot, you can then perform whatever action you wish.
Hope this helps! :)
Ok, from what I understand of your question, you have a large image which contains different objects you want your player to interact with, yes? By which I mean, the image file itself has doors or hills or other things which the player would interact with.
This is a bad idea, honestly, so I hope I misunderstood. It is far better to have your background image just be something generic and make all interactive objects classes within your game. If you do this, then you can have your object classes contain behavior to intersect with each other either based on their distance (circle collision) or based on a bounding box you define for them.
Circle Collision:
if (Math.Abs(Vector2.Distance(player.Position - obj.Position)) < player.Radius + obj.Radius)
//do the action
Rectangle Collision:
if (player.Bounds.Intersects(obj.Bounds))
//do the action
Also, if you are planning on making a 10,000 x 10,000 pixel image, understand that the XNA Content Pipeline will not import an image greater than 4,000 pixels to a side.
If you are set on having the player interact with pixels in the background of the image, you can either make an array of interactive object locations manually or you can use the Texture2D.GetData() method to load in the colors of every single pixel in the image for processing-- but be aware that this will take a long time, especially for large or numerous textures.
Related
First time doing this. I am currently building a bot using C# and want my bot to be able to move the mouse to a given point in a way that looks human. By this I am referring to the dragging of the mouse when a human moves the cursor to a point they are trying to click on. Currently my C# bot moves the mouse instantly to the location which doesn't look human.
private static Point[] FindColor(Color color)
{
int searchValue = color.ToArgb();
List<Point> result = new List<Point>();
using (Bitmap bmp = GetScreenShot())
{
for (int x = 0; x < bmp.Width; x++)
{
for (int y = 0; y < bmp.Height; y++)
{
if (searchValue.Equals(bmp.GetPixel(x, y).ToArgb()))
result.Add(new Point(x, y));
}
}
}
return result.ToArray();
}
// FUNCTIONS OCCUR BELOW
// Error message if program could not find bitmap within screenshot show error message
Color myRgbColor = new Color(); // Creates new colour called myRgbColor
myRgbColor = Color.FromArgb(51, 90, 9); // This colour equals the RGB value
Point[] points = FindColor(myRgbColor); // Create an array called points which list all the points found in the screen where the RgB value matches.
if (points.Length > 0)
{
Cursor.Position = points[2]; // Move mouse cursor to first point (Point 0)
Thread.Sleep(0200);
MouseClick();
}
if (points.Length == 0)
{
MessageBox.Show("No matches!"); // Return error
goto checkore;
}
You're going to want to use some kind of Timer with a callback, to move the mouse incrementally, step by step. As for the movement itself, you have a world of possibilities, but it's all maths.
So, let's decompose the problem.
What is a natural mouse movement?
Position change rate
It doesn't necessarilly looks like it, but when you move your mouse, you're simply setting its position multiple times per seconds.
The amount of times the position changes per second is equivalent to the polling rate of your mouse. The default polling rate for USB mice is 125Hz (or 125 position changes per second, if you will). This is the value we'll use for our Timer: its callback will be called 125 times per second.
var timer = new Timer(1000 / 125d);
timer.Elapsed += MoveMouse;
void MoveMouse(object sender, ElpasedEventArgs e) { }
Speed and acceleration
When you move your mouse, the distance between two cursor positions is not constant, because you're fast when you start moving your mouse, but you slow down when you get close to the item you want your cursor to be on.
There are also two ways I personally usually move my mouse depending on the context/mood:
One fast uniform movement to get close to the destination, then one slow to correct and get on it (I'll usually go past the destination during the first move)
One medium-slow movement with a small deceleration, follow by a stronger deceleration at the end
The overall speed of the movement also depends on three factors:
The distance between your cursor and the destination
The size of the destination area
Your personal speed
I have absolutely NO IDEA how to work out the formula based on these factors, that's gonna be a work of trial and error for yourself.
This one is purely math and observation based, and will be tricky to get perfectly right, if ever; every person moves their mouse a different way.
The solution I can offer you is to simply forget about deceleration, correction and so on, and just divide your movement into equal steps. That has the merit of being simple.
using System;
using System.Timers;
using System.Drawing;
public class Program
{
static int stepCount = 0;
static int numberOfSteps = 0;
static float stepDistanceX = 0;
static float stepDistanceY = 0;
static PointF destinationPoint;
static Timer timer;
public static void Main()
{
int timerStepDurationMs = 1000 / 125;
PointF currentPoint = Cursor.Position;
destinationPoint = new PointF(2000, 1800); // or however you select your point
int movementDurationMs = new Random().Next(900, 1100); // roughly 1 second
int numberOfSteps = movementDurationMs / timerStepDurationMs;
stepDistanceX = (destinationPoint.X - currentPoint.X) / (float)numberOfSteps;
stepDistanceY = (destinationPoint.Y - currentPoint.Y) / (float)numberOfSteps;
timer = new Timer(timerStepDurationMs);
timer.Elapsed += MoveMouse;
timer.Start();
while (stepCount != numberOfSteps) { }
}
static void MoveMouse(object sender, ElapsedEventArgs e)
{
stepCount++;
if (stepCount == numberOfSteps)
{
Cursor.Position = destinationPoint;
timer.Stop();
}
Cursor.Position.X += stepDistanceX;
Cursor.Position.Y += stepDistanceY;
}
}
Note that I haven't tested with "Cursor", but with some PointF variable instead. It seems to work fine here: dotnetfiddle.
So i want to align 2 objects together on the left side of the object that is the furthest to the left. So i'll sketch out a scenario:
There are 2 images on random positions on the board. You select both images(with a selection tool that has been made) and you than click: "Align objects to the left"
The image that is the furthest to the RIGHT should than snap to the same position of the edge on the left side of the other image. So when clicking the button, my code should calculate both left sides(the edge of the image on the left) of the images position, than check which one if the furthest to the right on the canvas, and move that one to the same X axis as the other image.
This way the end result will be the images will be on the exact same X axis. So if image 1 is on -73 & Image 2 is on -50, image 2 should than also move to -73, regardless of the rotation of either images.
Currently i can only find out how to find the middle position of the image, my code looks like this atm:
using com.company.program.core.pageObjects;
using com.company.program.ui.colorPicker;
using UnityEngine;
namespace com.company.program.core.SelectionManager
{
public static class SelectionAlignment
{
public static void AlignLeft(PageObjectBase pageObject)
{
Debug.Log("Let's check if this is a group first!");
if (pageObject is PageObjectGroup)
Debug.Log("Now we can AlignLeft!");
PageObjectGroup group = (PageObjectGroup)pageObject;
foreach (PageObjectBase objectBase in group.Children)
{
//objectBase.transform.position
Debug.Log("Position is now" + objectBase.transform.position);
Debug.Log("Left Position is" + objectBase.transform.position + -objectBase.transform.right);
}
}
}
}
}
Note: I have no moving function yet as im first trying to figure out what the position of the most left side of the image is. The first Debug.log works and displays the normal position(middle point of image). The second one doesn't work, and displays the same. Both images get instantiated during runtime.
Hopefully this is enough information, i'm a long time lurker but have never posted anything myself, so be gentle on me if i forgot to add information.
From your question left means a smaller X value.
So in general the left edge of an image (assuming PageObjectBase somehow inherits from MonoBehaviour and you are speaking about Image component from Unity UI with a RectTransform)
is the most left of all four corners of the image. You can get all four corners by using GetWorldCorners
private float GetLeftEdge(PageObjectBase obj)
{
RectTransform rectTransformComponent = obj.gameObject.GetComponent<RectTransform>();
if(!rectTransformComponent)
{
Debug.LogError("No Image component found", this);
return 0;
}
Vector3[] v = new Vector3[4];
rectTransformComponent.GetWorldCorners(v);
float mostLeftCorner = float.MaxValue;
foreach(var pos in v)
{
mostLeftCorner = Mathf.Min(mostLeftCorner, pos.x);
}
return mostLeftCorner;
}
This should also work if the images are rotated.
If you are not using RectTransform you have to get the width another way somehow but the rest stays the same.
Than in your loop you first have to get the smallest (most left) edge so I would split it in two loops:
// Start with the max float value so any other value should be smaller
float mostLeftEdge = float.MaxValue;
PageObjectBase referenceToMostLeftObject;
// Get the most left position and object reference
foreach (PageObjectBase objectBase in group.Children)
{
float leftEdge = GetLeftEdge(objectBase);
if(leftEdge < mostLeftEdge)
{
referenceToMostLeftObject = objectBase;
mostLeftEdge = leftEdge;
}
}
// Now you have the most left edge value and the object which is your reference
// Just a little safety skip to not move to strange values
if(referenceToMostLeftObject == null || Mathf.Approximately(mostLeftEdge, float.MaxValue))
{
Debug.LogError("Ups, I think something went wrong getting the mostLeftEdge", this);
return;
}
// Move the other objects to match with that edge
foreach (PageObjectBase objectBase in group.Children)
{
// Skip the reference object
if(objectBase == referenceToMostLeftObject) continue;
// First get the difference
float leftEdge = GetLeftEdge(objectBase);
// Should always be negative
float difference = mostLeftEdge - leftEdge;
// Than move it there
var current = objectBase.transform.position;
// Since difference should be negative
// Adding it to the current position should result in the wanted position
var newPosition = new Vector3(current.x + difference, current.y, current.z);
objectBase.transform.position = newPosition;
}
Recently I've been trying to make a 2D game in XNA, but I seem to have hit a dead end. No mater where I look on the internet, I can't seem to find any examples of how to make two objects collide in XNA. I know perfectly well about how to detect if something is colliding, just not what to put between the if statement.
In my case it's trying to make a player not pass through any blocks on the screen. I've tried several ways, but none of them seems to work. :(
Thanks in advance!
So, this is sort of a dirty solution, but you could save the position of where you are, move, and then if you collide, revert back to the original position.
Here's a code example, providing your method to check for collision is called doesCollide() and your method to do the game logic and move the player accordingly is called update().
Also, getX(), getY(), setX() and setY() are just methods to get/set the coordinates of the player.
int lastX = player.getX();
int lastY = player.getY();
player.update();
if(player.doesCollide()){
player.setX(lastX);
player.setY(lastY);
}
This method especially faces problems, when the player is moving at a high speed, because then the player might glitch through obstacles or not be able to get close to walls.
Here's a solution that fixes that, but it is even dirtier:
int lastX = player.getX();
int lastY = player.getY();
player.update();
int moveX = player.getX() - lastX;
int moveY = player.getY() - lastY;
player.setX(lastX);
player.setY(lastY); //we're basically figuring out where the player would move
int ratio = moveY / moveX;
for(int i = 0; i < moveX; i++){ //we move the player pixel by pixel
player.setX(lastX + i);
player.setY(lastY + (int) (i * ratio));
if(player.doesCollide()){ //we revert the last pixel move
player.setX(lastX + i - 1);
player.setY(lastY + (int) ((i - 1) * ratio));
}
}
This is a follow up question to a question that I posted last night. I have to write a game in a Windows Form for school, and I am creating a maze game in which a player must navigate through a maze before they are killed. As a maze game, some collision detection must be used to make sure that the player doesn't simply run through the walls (this would be quite a boring game). I've implemented a feature which prevents this based on the question that I asked last night, but I'm getting some weird results.
When the player touches a wall, the game stops them, and the player ends up getting stuck. The player CANNOT move unless they press a combination of keys to move through the wall (my game uses WASD, so if I touch a wall, I can press W + A and go through the wall to the other side where my player gets unstuck).
This is my collision code:
// This goes in the main class
foreach (Rectangle wall in mazeWalls)
{
if (playerRectangle.IntersectsWith(wall))
{
player.Stop();
}
}
This is the player's movement code:
public void Move(Direction dir)
{
// First, check & save the current position.
this.lastX = this.x;
this.lastY = this.y;
if (dir == Direction.NORTH)
{
if (!CheckCollision())
{
this.y -= moveSpeed;
}
else
{
this.y += 1;
}
}
else if (dir == Direction.SOUTH)
{
if (!CheckCollision())
{
this.y += moveSpeed;
}
else
{
this.y -= 1;
}
}
else if (dir == Direction.EAST)
{
if (!CheckCollision())
{
this.x += moveSpeed;
}
else
{
this.x -= 1;
}
}
else if (dir == Direction.WEST)
{
if (!CheckCollision())
{
this.x -= moveSpeed;
}
else
{
this.x += 1;
}
}
}
My CheckCollision() method:
private bool CheckCollision()
{
// First, check to see if the player is hitting any of the boundaries of the game.
if (this.x <= 0)
{
isColliding = true;
}
else if (this.x >= 748)
{
isColliding = true;
}
else if (this.y <= 0)
{
isColliding = true;
}
else if (this.y >= 405)
{
isColliding = true;
}
else if (isColliding)
{
isColliding = false;
}
// Second, check for wall collision.
return isColliding;
}
The Stop() method:
public void Stop()
{
this.x = lastX;
this.y = lastY;
}
Here is a gif that I have uploaded so that you can see the behavior of the player with the maze walls. Notice how he slides through the walls and repeatedly gets stuck.
My question is how do I get this player to stop sticking and actually be able to slide and move with the walls? I've tried multiple collision patterns, and used last night's (very helpful) answer, but he won't stop sticking to the walls! Let me know if you need any other details/information.
EDIT: The Input code, as requested by Dan-o: http://pastebin.com/bFpPrq7g
Game design is a complicated subject. There are some pretty well documented strategies for implementing 2D maze games. The most anyone can do here is to make general suggestions based on what you've done knowing that a commercial game is not what trying to make here. So anyhow, I'll throw in my two cents. I've only done anything like this in OpenGL, not with Windows Forms.
The first thing I see is that your sprite doesn't stay centered in it's lanes. Calculating that will ultimately make things easier because there are always only 4 possible directions that the player can be moving. North, South, East, and West don't mean as much when diagonal is also possible.
Design your gameboard so that your walls and your lanes are the same width. Use evenly spaces rows and columns. Since you're using a fixed board size, this should be as simple as dividing your width and height by the number of rows and columns you want.
Once you've done this, you will always know what lane you're in based on your x and y coordinates. If your columns are 80 pixels wide, for instance, and you're at x = 160 then you know you're in column 2 (1 in a 0-based array). This is the only way you are going to be able to put enemies on the board and be able to programmatically track where they are going. Also, you'll be able to size your players and enemies appropriately for the lanes.
Let's say your rows and columns are 80Wx60H pixels (they can be whatever you like best). Now let's say that your player is moving East starting from 0, 160. And, he can move North and South when he gets to column 3 (2 in a zero-based model), according to your map. Meaning, when he gets to 160, 160. Remember, if x = 0 starts column 1, then 80 starts column 2, and so on.
Forgetting collisions for a moment, you could use logic like this.
RectangleF playerRectangle = new RectangleF();
int COLUMN_WIDTH = 80;
int ROW_HEIGHT = 60;
if (playerRectangle.IntersectsWith(wall)){
int column = playerRectangle.X / COLUMN_WIDTH;
//----------------------------------------------
// This will return false if the player
// is not positioned right at the column. The
// result of % will contain decimal digits.
// playerRectangle.X has to be a float though.
//----------------------------------------------
if(column % 1 == 0){
//--------------------------------------------
// do this based on your keyboard logic. this
// is pseudo-code
//--------------------------------------------
if(keys == keys.UP){
// Move up
}
else if(keys == keys.DOWN){
// Move down
}
}
}
Another thing you'll want to do is to store an orientation property with your walls. That way when you collide with one, you'll know what your options are for movement. If the wall you collide with is WallOrientation.NorthSouth, you can only move North or South once you hit it. Or, you can go in reverse to the direction you hit it from. If no keys are pressed you sit still. Some thing like this will do.
public enum WallOrientation{
NorthSouth,
EastWest
}
None of this code is tested. I just wrote it on the fly so there could be mistakes. I'm just trying to give you some ideas. I hope this advice helps you out some.
Okay, so, I am making a small tile-based digging game, now I want to do collision. How would I go about doing this correctly? I know how to check if the player collides with a tile, but I don't know how to actually make the player stop when it hits a wall.
This is the game, I got 20x20 tiles here.
This is the code I'm using atm:
foreach (Tile tiles in allTiles)
{
if (ply.rect.Intersects(tiles.rect))
{
if (tiles.ID != -1 && tiles.ID != 1)
{
if (ply.X > tiles.X)
{
Console.WriteLine("Right part.");
ply.X = tiles.pos.X + 30;
}
if (ply.X <= tiles.X)
{
Console.WriteLine("Left part.");
ply.X = tiles.pos.X - 30;
}
if (ply.Y > tiles.Y)
{
Console.WriteLine("Bottom part.");
ply.Y = tiles.pos.Y + 30;
}
if (ply.Y <= tiles.Y)
{
Console.WriteLine("Upper part.");
ply.Y = tiles.pos.Y - 30;
}
}
}
}
What type of collision detection are you using?
If your using Rectangles and the '.intersects' method you can always declare a bool to make sure your character is touching the floor. If he isn't you apply a Gravity Vector to make it fall to the next Tile with a different Rectangle so when he hits it he's going to stop falling.
If you want to block him from side to side just test to see which side of the rectangle he is touching and block him from moving on the 'X' axis.
E.g if he is going right and intersects with the left part of a rectangle, block is 'GoingRight' movement.
if(myCharacterRectangle.Intersects(tileRectangle)
{
if(myCharacterPosition.X > (tilePosition.X)
{
//You know the character hits the Right part of the tile.
}
if(mycharacterPosition.X <= tilePosition.X)
{
//You know the character hits the Left Part of the tile.
}
}
And same goes for the Position.Y if you want to test the Top or Bottom.
If you want to use Pixel by Pixel collision detection using Matrices I know a good tutorial here.
The detection will return a 'Vector2(-1,-1)' if there is no collision.
If there is a one the method will return the coordinates of the collisions which makes it even easier to determine what part of the tile your character is touching.
Hope this helps. Good Luck with your game.