Sprite follows mouse [duplicate] - class

This question already has answers here:
How to make an enemy follow the player in pygame?
(5 answers)
How to make smooth movement in pygame
(2 answers)
pygame 2 dimensional movement of an enemy towards the player, how to calculate x and y velocity?
(1 answer)
how to make particles follow my mouse in pygame
(2 answers)
Closed 5 months ago.
am I missing something?
I'm trying to make a sprite follow the mouse, but when I try to return the position of the ship from the sprite to compare it with the mouse position x, y are totally ignored.
I have done this but keeping all the code within the sprite but for some reason it messes up the collide in pygame.
Please help there's got to be a way of getting x and y out of the class!
import pygame
speed = 10
move_right = False
move_left = False
move_down = False
move_up = False
clock = pygame.time.Clock()
FPS = 60
GREEN = (0, 255, 0)
screen = pygame.display.set_mode((800, 800))
x, y = pygame.mouse.get_pos()
class Spaceship(pygame.sprite.Sprite):
def __init__(self, x, y, scale):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("ship.png")
self.image = pygame.transform.scale(self.image, (int(self.image.get_width() * scale), int(self.image.get_height() * scale)))
self.rect = self.image.get_rect()
self.rect.center = [x, y]
self.speed = 5
def move(self, move_right, move_left, move_down, move_up, x, y):
dx = 0
dy = 0
if move_right:
dx = self.speed
if move_left:
dx = -self. speed
if move_down:
dy = self.speed
if move_up:
dy = -self.speed
self.rect.x += dx
self.rect.y += dy
if self.rect.x >= 790:
self.rect.x = 790
if self.rect.x <= 10:
self.rect.x = 10
if self.rect.y <= 10:
self.rect.y = 10
if self.rect.y >= 790:
self.rect.y = 790
x = self.rect.x
y = self.rect.y
return x, y
def draw(self):
pygame.draw.rect(screen,(GREEN), self.rect, 2)
screen.blit(self.image, self.rect)
ship = Spaceship(x, y, 1)
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pos = pygame.mouse.get_pos()
dx = (pos[0])
dy = (pos[1])
clock.tick(FPS)
if x < dx:
move_right = True
else: move_right = False
if x > dx:
move_left = True
else: move_left = False
if y < dy:
move_down = True
else: move_down = False
if y > dy:
move_up = True
else: move_up = False
print(dx, dy)
ship.move(move_right, move_left, move_down, move_up, x, y)
ship.draw()
pygame.display.update()
pygame.quit()

Related

Where a vector would intersect the screen if extended towards it's direction (swift)

I'm trying to write a function in swift, which returns a CGPoint where the extension of a vector (which is within a screen) will intersect the screen. Let's assume that the screen is 800 x 600. It's like the scheme:
The function should have the following parameters:
func calcPoint(start: CGPoint, end: CGPoint) -> CGPoint
start: CGPoint(x: x1, y: y1) - this is the beginning of the vector.
end: CGPoint(x: x1, y: y1) - this is the end point of the vector.
the return point is the one at which the vector intersects the screen (CGPoint(x: x3, y: y3) as shown at the scheme).
The values for the vector start and end are aways points within the screen (the rectangle 0, 0, 800, 600).
EDIT (for Alexander):
Is there a formula, which in the given situation will make it easy to write the function, in not the obvious way using if ... else ... and triangle vertices ratio?
To compute point E you can look at the triangles given by your setting. You have the Triangle ABC and DBE. Note that they are similar, such that we can set up following relation AB : AC = DB : DE using the intercept theorem (AB etc. stands for the line segment between A and B). In the given setting you know all points but E.
Using start and end Points from given setting:
In case start and end have the same x or y-coordinate it is only the top bottom or left right border with the same coordinate.
Using the absolute values it should work for all four corners of your rectangle. Then of course you have to consider E being out of your rectangle, again the same relation can be used AB : AC = D'B : D'E'
A pure swift solution for everyone interested in such (thanks to Ivo Ivanoff):
// Example for iOS
/// The height of the screen
let screenHeight = UIScreen.main.bounds.height
/// The width of the screen
let screenWidth = UIScreen.main.bounds.width
func calculateExitPoint(from anchor : CGPoint, to point: CGPoint) -> CGPoint {
var exitPoint : CGPoint = CGPoint()
let directionV: CGFloat = anchor.y < point.y ? 1 : -1
let directionH: CGFloat = anchor.x < point.x ? 1 : -1
let a = directionV > 0 ? screenHeight - anchor.y : anchor.y
let a1 = directionV > 0 ? point.y - anchor.y : anchor.y - point.y
let b1 = directionH > 0 ? point.x - anchor.x : anchor.x - point.x
let b = a / (a1 / b1)
let tgAlpha = b / a
let b2 = directionH > 0 ? screenWidth - point.x : point.x
let a2 = b2 / tgAlpha
exitPoint.x = anchor.x + b * directionH
exitPoint.y = point.y + a2 * directionV
if (exitPoint.x > screenWidth) {
exitPoint.x = screenWidth
} else if (exitPoint.x < 0) {
exitPoint.x = 0;
} else {
exitPoint.y = directionV > 0 ? screenHeight : 0
}
return exitPoint
}
Any kind of optimizations are welcomed ;-)
There is no single formula, because intersection depends on starting point position, line slope and rectangle size, and it may occur at any rectangle edge.
Here is approach based on parametric representation of line. Works for any slope (including horizontal and vertical). Finds what border is intersected first, calculates intersection point.
dx = end.x - start.x
dy = end.y - start.y
//parametric equations for reference:
//x = start.x + dx * t
//y = start.y + dy * t
//prerequisites: potential border positions
if dx > 0 then
bx = width
else
bx = 0
if dy > 0 then
by = height
else
by = 0
//first check for horizontal/vertical lines
if dx = 0 then
return ix = start.x, iy = by
if dy = 0 then
return iy = start.y, ix = bx
//in general case find parameters of intersection with horizontal and vertical edge
tx = (bx - start.x) / dx
ty = (by - start.y) / dy
//and get intersection for smaller parameter value
if tx <= ty then
ix = bx
iy = start.y + tx * dy
else
iy = by
ix = start.x + ty * dx
return ix, iy

Fast CVX solvers in Matlab

I am wondering what is the fastest convex optimizer in Matlab or is there any way to speed up current solvers? I'm using CVX, but it's taking forever to solve the optimization problem I have.
The optimization I have is to solve
minimize norm(Ax-b, 2)
subject to
x >= 0
and x d <= delta
where the size of A and b are very large.
Is there any way that I can solve this by a least square solver and then transfer it to the constraint version to make it faster?
I'm not sure what x.d <= delta means, but I'll just assume it's supposed to be x <= delta.
You can solve this problem using the projected gradient method or an accelerated projected gradient method (which is just a slight modification of the projected gradient method, which "magically" converges much faster). Here is some python code that shows how to minimize .5|| Ax - b ||^2 subject to the constraint that 0 <= x <= delta using FISTA, which is an accelerated projected gradient method. More details about the projected gradient method and FISTA can be found for example in Boyd's manuscript on proximal algorithms.
import numpy as np
import matplotlib.pyplot as plt
def fista(gradf,proxg,evalf,evalg,x0,params):
# This code does FISTA with line search
maxIter = params['maxIter']
t = params['stepSize'] # Initial step size
showTrigger = params['showTrigger']
increaseFactor = 1.25
decreaseFactor = .5
costs = np.zeros((maxIter,1))
xkm1 = np.copy(x0)
vkm1 = np.copy(x0)
for k in np.arange(1,maxIter+1,dtype = np.double):
costs[k-1] = evalf(xkm1) + evalg(xkm1)
if k % showTrigger == 0:
print "Iteration: " + str(k) + " cost: " + str(costs[k-1])
t = increaseFactor*t
acceptFlag = False
while acceptFlag == False:
if k == 1:
theta = 1
else:
a = tkm1
b = t*(thetakm1**2)
c = -t*(thetakm1**2)
theta = (-b + np.sqrt(b**2 - 4*a*c))/(2*a)
y = (1 - theta)*xkm1 + theta*vkm1
(gradf_y,fy) = gradf(y)
x = proxg(y - t*gradf_y,t)
fx = evalf(x)
if fx <= fy + np.vdot(gradf_y,x - y) + (.5/t)*np.sum((x - y)**2):
acceptFlag = True
else:
t = decreaseFactor*t
tkm1 = t
thetakm1 = theta
vkm1 = xkm1 + (1/theta)*(x - xkm1)
xkm1 = x
return (xkm1,costs)
if __name__ == '__main__':
delta = 5.0
numRows = 300
numCols = 50
A = np.random.randn(numRows,numCols)
ATrans = np.transpose(A)
xTrue = delta*np.random.rand(numCols,1)
b = np.dot(A,xTrue)
noise = .1*np.random.randn(numRows,1)
b = b + noise
def evalf(x):
AxMinusb = np.dot(A, x) - b
val = .5 * np.sum(AxMinusb ** 2)
return val
def gradf(x):
AxMinusb = np.dot(A, x) - b
grad = np.dot(ATrans, AxMinusb)
val = .5 * np.sum(AxMinusb ** 2)
return (grad, val)
def evalg(x):
return 0.0
def proxg(x,t):
return np.maximum(np.minimum(x,delta),0.0)
x0 = np.zeros((numCols,1))
params = {'maxIter': 500, 'stepSize': 1.0, 'showTrigger': 5}
(x,costs) = fista(gradf,proxg,evalf,evalg,x0,params)
plt.figure()
plt.plot(x)
plt.plot(xTrue)
plt.figure()
plt.semilogy(costs)

Application starts going nuts after a while

I've recently started using corona SDK and I'm trying to build an app for the iPhone. Now the main idea behind it, is that there are birds flying and you have to shoot them. The birds get a random spot on the screen as their target, and navigate towards it. The app runs fine for about 30 secs - 1 minute, but then suddenly it starts speeding up enormously fast and I don't know why.
And help regarded this is deeply appreciated.
display.setDefault("background", 246, 255, 100)
_W = display.contentWidth;
_H = display.contentHeight;
target = {}
birdPosition = {}
print(_W.." ".._H)
--getting a random location on the screen
local x = math.random(_W)
local y = math.random(_H)
--this checks whether the image will be placed partially off the screen
if x > _W - 42 then
x = _W - 42
end
if y > _H - 42 then
y = _H - 42
end
birdPosition[1] = x
birdPosition[2] = y
local equation = 0
--will be used to see whether the movement will be more vertically than horizontally
local moveVertically = false
local bird = display.newImage("images/bird.png", x, y)
--when the bird is touched, it is removed
function bird:touch()
bird:removeSelf()
end
bird:addEventListener("touch", bird)
--get a new random position
function getNewPosition()
--loop = 50
--getting a random next spot to move to + a check
x = math.random(_W)
y = math.random(_H)
if x > _W - 42 then
x = _W - 42
end
if y > _H - 42 then
y = _H - 42
end
--placing the co-ordinates
target[1] = x
target[2] = y
local smallest
birdPosition[1] = bird.x
birdPosition[2] = bird.y
local diffY
--this check is done so we get a positive equation
if x > bird.x then
diffX = x - bird.x
else
diffX = bird.x - x
end
if y > bird.y then
diffY = y - bird.y
else
diffY = bird.y - y
end
--this check is done so that the equation will always be bigger as 1. This also checks
--whether it will move more vertically than horizontally by putting the boolean true or false
if diffX >= diffY then
equation = diffX/diffY
smallest = diffY
moveVertically = false
else
equation = diffY/diffX
smallest = diffX
moveVertically = true
end
--print("birdPosition X: "..birdPosition[1].. " birdPosition Y: "..birdPosition[2])
--print("Target X: " .. target[1].." Target Y: "..target[2])
--[[
if for instance diffX = 100 and diffY = 50:
smallest will be 50, because the move will be vertically and will only have to be executed 50 times
to give it the effect that it flies quick
]]--
tmr = timer.performWithDelay(10, moveBird, smallest)
end
function moveBird()
if moveVertically == true then
if target[1] >= birdPosition[1] then
bird.x = bird.x + 1
else
bird.x = bird.x - 1
end
if target[2] >= birdPosition[2] then
bird.y = bird.y + equation
else
bird.y = bird.y - equation
end
else
if target[1] >= birdPosition[1] then
bird.x = bird.x + equation
else
bird.x = bird.x - equation
end
if target[2] >= birdPosition[2] then
bird.y = bird.y + 1
else
bird.y = bird.y - 1
end
end
--print("Bird X: "..bird.x .. " Bird Y: " .. bird.y)
--this checks every possibility to get a new position
if bird.x == target[1] or bird.y == target[2] or bird.y < 0 or bird.x > 640 or bird.x < 0 or bird.y > 960 then
getNewPosition()
end
end
getNewPosition()
One error in timer.performWithDelay(10, moveBird, smallest).
The timer is not called the correct way: the third argument should be the number of iteration (so 1), and not smallest.
See the doc here

How to drag a view, along the circumference of an oval?

I have an Oval and a view on the circumference of the Oval. When you try to drag the view, the view should be moved only on the circumference of the Oval. How can I achieve this?
Any sample equation would be helpful. Thanks.
CGPoint ovalCenter;
CGSize ovalSize;
- (CGPoint)constrainPointToOval:(CGPoint)point
{
float angle = atan2(point.y - ovalCenter.y, point.x - ovalCenter.x);
return CGPointMake(ovalSize.width * cosf(angle), ovalSize.height * sinf(angle));
}
You'll need to set ovalCenter and ovalSize elsewhere. Then run the touch position through this before setting the location of the view.
I have figured out a solution for getting a constrained drag along the sides of a square.
If anyone can improve the code, or have a better solution, you most welcome.
- (CGPoint) constrainPointToSquare:(CGPoint) point
{
float pi = 3.14159265;
float s1,s2;
CGPoint squareDragPoint;
float squareSize = 200.0;
float angle;
angle = atan2 (point.y - mCenter.y, point.x - mCenter.x);
float x1 = point.x;
float x2 = mCenter.x;
float y1 = point.y;
float y2 = mCenter.y;
if (((3*(pi/4) <= angle && pi >= angle) || (-pi <= angle && -3*(pi/4) >= angle)))//left
{
s1 = y2 - squareSize;
s2 = x2 - squareSize * ((y1-y2)/(x1-x2));
squareDragPoint = CGPointMake(s1, s2);
}
else if (((-(pi/4) <= angle && 0.0 >= angle) || (0.0 <= angle && (pi/4) >= angle))) //right
{
s1 = y2 + squareSize;
s2 = x2 + squareSize * ((y1-y2)/(x1-x2));
squareDragPoint = CGPointMake(s1, s2);
}
else if (((-3*(pi/4) <= angle && -(pi/2) >= angle) || (-(pi/4) >= angle && -(pi/2) <= angle))) //top
{
s1 = x2 - squareSize;
s2 = y2 - squareSize * ((x1-x2)/(y1-y2));
squareDragPoint = CGPointMake(s2, s1);
}
else if (((3*(pi/4) >= angle && (pi/2) <= angle) || (pi/4 <= angle && (pi/2) >= angle))) //bottom
{
s1 = x2 + squareSize;
s2 = y2 + squareSize * ((x1-x2)/(y1-y2));
squareDragPoint = CGPointMake (s2, s1);
}
return squareDragPoint;
}

Box2d Calculating Trajectory

I'm trying to make physics bodies generated at a random position with a random velocity hit a target. I gleaned and slightly modified this code from the web that was using chipmunk to run in Box2d
+ (CGPoint) calculateShotForTarget:(CGPoint)target from:(CGPoint) launchPos with:(float) velocity
{
float xp = target.x - launchPos.x;
float y = target.y - launchPos.y;
float g = 20;
float v = velocity;
float angle1, angle2;
float tmp = pow(v, 4) - g * (g * pow(xp, 2) + 2 * y * pow(v, 2));
if(tmp < 0){
NSLog(#"No Firing Solution");
}else{
angle1 = atan2(pow(v, 2) + sqrt(tmp), g * xp);
angle2 = atan2(pow(v, 2) - sqrt(tmp), g * xp);
}
CGPoint direction = CGPointMake(cosf(angle1),sinf(angle1));
CGPoint force = CGPointMake(direction.x * v, direction.y * v);
NSLog(#"force = %#", NSStringFromCGPoint(force));
NSLog(#"direction = %#", NSStringFromCGPoint(direction));
return force;
}
The problem is I don't know how to apply this to my program, I have a gravity of -20 for y but putting 20 for g and a lower velocity like 10 for v gets me nothing but "No Firing Solution".
What am I doing wrong?
A lower velocity of 10 is never going to work the projectile doesn't have enough power to travel the distance.
The error in the calculation is that everything is in meters except for the distance calculations which are in pixels!
Changing the code to this fixed the crazy velocities i was getting:
+ (CGPoint) calculateShotForTarget:(CGPoint)target from:(CGPoint) launchPos with:(float) velocity
{
float xp = (target.x - launchPos.x) / PTM_RATIO;
float y = (target.y - launchPos.y) / PTM_RATIO;
float g = 20;
float v = velocity;
float angle1, angle2;
float tmp = pow(v, 4) - g * (g * pow(xp, 2) + 2 * y * pow(v, 2));
if(tmp < 0){
NSLog(#"No Firing Solution");
}else{
angle1 = atan2(pow(v, 2) + sqrt(tmp), g * xp);
angle2 = atan2(pow(v, 2) - sqrt(tmp), g * xp);
}
CGPoint direction = CGPointMake(cosf(angle1),sinf(angle1));
CGPoint force = CGPointMake(direction.x * v, direction.y * v);
NSLog(#"force = %#", NSStringFromCGPoint(force));
NSLog(#"direction = %#", NSStringFromCGPoint(direction));
return force;
}