Xna 4.0 RTS camera - xna

How do I make a RTS camera so that when the mouse is at the edge of the window, it will move either left/right/up/down. I been trying to create an invisible box at the side of the screen so that when the mouse is at the box it will move the camera, but it still doesn't work. Please help!

Building upon what #Davor Mlinaric said, using the mouses x and y coordinates (which can be gotten from Mouse.GetState()), and testing whether those coordinates come in contact with the top, bottom and sides of the screen.
It would be a good start to set where those boxes will be something along the lines of:
GraphicsDevice.Viewport.Width/Height -/+ offset
Where offset is the amount of distance from the top,bottom or side.
Then test where the mouse position is, with a boolean.
boolean inTheZone = false;
//Bottom Box
if(Mouse.GetState().Y > GraphicsDevice.Viewport.Height - offset)
{
//Move camera in the y axis downwards (+).
inTheZone = true;
}
else
{
inTheZone = false;
}
and then the same for the 4 remaining sides.
Notice ive also used Y here, depending on how you set up the camera this may change to Z.
I hope this helps

Related

Center a generated Row in a SpriteKit Scene

I am making a Breakout Game and the Game generates rows from how ever many bricks I want in that row. But I cannot get the rows to start in the center. How would I achieve this, here is my current code.
I've tried numerous things, but the closest I got was to get them all to be in the middle, but the should spread out from the middle.
What I would like to achieve should look something like this.
If you have the maximum row size available, a simple way is to include an offset when you calculate the x coordinate.
let maxRow = ... // whatever the maximum row size is
let padding = (maxRow - row) / 2 // how many blocks to skip on the left
for i in 1...row {
// your block creation loop
let x = 15 + (i + padding) * Int(brick.size.width)
// make the brick at x, y
}
If things might not divide evenly (e.g., if maxRow is 15 like it seems to be in your pictures, but row could be 4) then you have to decide on what behavior you'd like. The above will keep bricks aligned because the integer division in calculating padding will truncate; the left and right padding won't be the same. If you use floating division and get a padding like 3.5, you'd get perfectly centered rows but odd rows and even rows would have different alignment.
If your problem is that you want things to appear in an animated way (like in your picture), then things are more complicated. Instead of generating based on the sequence 1, 2, ..., row, it's probably easier to think about generating from the sequence 0, +1, -1, +2, -2, ... After generating the center brick, you'd do the generation of additional bricks in pairs. The x coordinates would be calculated as xCenter + i * Int(brick.side.width).
You're adding the bricks into a parent SKNode (using addChild(_:)). Everything added in that parent node is relative to its coordinate space.
Try adding a brick at y: 0 and see where will it be positioned. If your scene has the anchorPoint at 0.5, you will likely see the brick in the center of the screen. From there, you go up or down (positive or negative y values) to show other rows.
To better understand how the coordinate system works, see About SpriteKit Coordinate Systems.
It's the same for the x axis. If your bricks start from left to right, that means the parent node has its origin to the left of the screen.
To start from the middle, you need to know the middle point. One option is to make a container node, position that in the center of the screen, and add all the bricks there. Like that, the bricks can start at (0, 0).
let middle = CGPoint(x: scene!.size.width / 2, y: scene!.size.height / 2)
let container = SKNode()
container.position = middle
// inside makeBricks(), add everything inside container:
container.addChild(brick)
It really depends on how you set up your node hierarchy.

How to set where 0,0 coordinates are?

By default, 0,0 coordinates are in the top, left corner. However, for my scene, it would be very helpful if it was in my bottom, left corner.
Is that even possible? If so, how can I set that?
This is a mathematical approach which I think is a lot easier.
Simply define a function which converts your local Y coordinate to what Corona uses:
function localY ( y )
return 600-y --Assuming your screen size is 600 pixels
end
Then simply use
x, localY(y) instead of x,y
You can do the same for x if decided to change it.

How to prevent "mouse object" from moving throgh rectangles?

What am I trying to achieve?
I have a Sprite which is supposed to move with the mouse position (kinda like a cursor). In my case though I also have some other Textures (Obstacle-class). So if the mouse collides with such an obstacle I want the texture to stop moving in that direction.
What is the problem?
While the texture does follow the mouse and also does stop when the mouse "collides" with an obstacle, at some point the cursor is not within the Bounding Rectangle anymore, but on the other side of a wall for example. The consequence, the texture's position is updated to the mouse position and it suddenly appears behind the wall which is not a desired behavior.
My collision method.
private void CheckCollision(List<Obstacle> _obstacleList, MouseState mState)
{
int xOffset = oldMouseState.X - mState.X;
int yOffset = oldMouseState.Y - mState.Y;
Vector2 offsetPosition = new Vector2(oldMouseState.X + xOffset,oldMouseState.Y + yOffset);
bool collides = false;
foreach (Obstacle obstacle in _obstacleList)
{
if (obstacle.BoundRectangle.Contains(offsetPosition))
{
collides = true;
}
}
if (!collides)
{
position = offsetPosition;
}
}
Question
What be a way to prevent the sprite to move through walls in my case?
Thanks in advance.
As you know, you can read the the mouse position by calling Mouse.GetState(). But you can also set the mouse position to whatever you want through Mouse.SetPosition(X,Y) and the mouse will go there.
So, if you are up against, say, an X barrier (vertical barrier), simply call
Mouse.SetPosition(oldMouseState.X, mState.Y);
and your mouse will not change its X value even if pushing your mouse in that direction, it will not go through the wall at all but it is allowed to go up and down just fine.
If you back off from the wall, simply don't call this line and it will operate like befor.
You could store the last (valid) known position of the mouse and the current position of the mouse (valid means the mouse isn't in a rectangle where it shouldn't be). When you hit a rectangle that the mouse shouldn't pass through with your current mouse position, you iterate back to the last valid position in a while loop and check if the mouse is still in the blocking sprite every time you moved the mouse closer to the valid position. If the mouse is outside the forbidden zone, you just exit the while loop and the mouse is quite close to the border of the obstacle.

Convert Scene's (x, y) to screen's (x, y)

I have an application built with SceneKit that is currently displaying several nodes. I can figure out which node is pressed and want to use that to make a label appear below the Node that was touched. Now, when I set the label's center the following way...
nameLabel.center = CGPointMake(CGFloat(result.node.position.x), CGFloat(result.node.position.y+20)
…it appears in the upper left corner since the node is on (1, 0). What I figured is that the sceneView's (0, 0) is in the center of the screen while the actual physical display's (0, 0) is in the top left corner.
Is there a way to convert the two different numbers into each other? (I could hardcode since I know where the Node's are or create a separate label for each Node but that is not really a perfect solution.)
Thanks in advance :)
You can use the projectPoint: method:
var projected = view.projectPoint(result.node.position))
//projected is an SCNVector3
//projected.x and y are the node's position in screen coordinates
//projected.z is its depth relative to the near and far clipping planes
nameLabel.center = CGPointMake(CGFloat(projected.x), CGFloat(projected.y+20)

Corona SDK: fill up a bar from left to right

I'm learning Corona SDK and am new to lua as well (i mainly do ruby and some javascript).
I have a bar that i want to fill up as the user does stuff. I've set it up as follows:
--outer rectangle
powerBar = display.newRect(210, 6, 24, 9)
powerBar.strokeWidth = 1
powerBar:setStrokeColor(254,203,50)
powerBar:setFillColor(0,0,0,0)
--inner rectangle which fills up
powerBarFill = display.newRect(211,7,0,7)
powerBarFill:setFillColor(234,183,30)
When the "stuff" happens, i add 1 to powerBarFill.width, which i thought would make it grow from left to right. But, it's actually growing out from the centre, ie its x is in the centre and the width extends either side from that.
Whats the best way to keep the left side static and grow the right side? Can i set it so that it's x position is actually on the left hand side rather than in the middle? Seems like that might do it.
cheers in advance
I've run into this problem as well when creating a progress bar. The problem is with the rect's reference point. The default reference point is in the center of an object, as you've noticed. You can use object:setReferencePoint() to change it. I believe you want to use the display.BottomLeftReferencePoint value:
powerBar:setReferencePoint(display.BottomLeftReferencePoint)
Keep in mind that you have to set this value before you set your x,y values. So in your case you'll need to set the reference point after creating the rectangle, and then assign values to x,y again (even though you already did this in the newRect constructor):
powerBar = display.newRect(210, 6, 24, 9)
powerBar:setReferencePoint(display.BottomLeftReferencePoint)
powerBar.x, powerBar.y = 210, 6
If it's width is from the X position on both sides:
1) It should start at:
Centre - (Width when it's full / 2)
2) Every frame, add:
incrs = 1 --Amount to increase by
width = width + incrs
x = x + incrs / 2

Resources