checkers game logic/pseudo code? - python

I am making a checkers game in python using the pyglet library. Up till now, I have been able to upload the graphics of the game. The problem is that I do not know how to make the logic/pseudo code of checkers. I do know that it is not possible for any of you to provide me the whole logic in here. So below are some ideas I have in mind. Please advice me if these ideas are correct and if any of them is wrong, what is the substitute?
1) Using an integer turn = 0 or 1, 0 means turn of black piece and 1 means turn of white piece.
2) Numbering the squares in the checkers board from 0 to 31.
3) Movement? Help me on this one. Just tell me the basic outline. I know that for the piece to move, there must not be any other piece in front or if opponent piece is there, it can capture it. This is the toughest part I can not figure out. Then, if there are two opponent pieces, it cannot capture the first piece as the way is blocked. Then, if an opponent's piece is infront of the player piece and opponents other piece is one space before its first piece, the player piece can jump two times and capture two pieces?
4) I have no idea about the king thing. If I can do the simple things first, I am sure I will be able to do this as well.
5)Win -> if all black/whitesprites,visible= false, particular player wins.
Here is my code below:
import pyglet
from pyglet.window import key
from pyglet.window import mouse
from pyglet.window import gl
class checkers(pyglet.window.Window):
blue = pyglet.resource.image('resources/blueSquare.bmp')
red = pyglet.resource.image('resources/redSquare.bmp')
blackP = pyglet.resource.image('resources/blackP.bmp')
whiteP = pyglet.resource.image('resources/whiteP.bmp')
spriteB = []
spriteW = []
screenWidth=600
screenHeight=600
x=None
y=None
w=None
h=None
def __init__(self):
super(checkers, self).__init__(self.screenWidth,self.screenHeight,
resizable=False,
caption="Checkers",
config=pyglet.gl.Config(double_buffer=True),
vsync=False
)
platform = pyglet.window.get_platform()
display = platform.get_default_display()
screen = display.get_default_screen()
self.x = 60
self.y = 60
self.red.width = self.x
self.red.height = self.y
self.blue.width = self.x
self.blue.height = self.y
self.blackP.height=self.y
self.blackP.width = self.x
self.whiteP.height = self.y
self.whiteP.width=self.x
self.h = self.red.height
self.w = self.red.width
self.x = (self.screenWidth - (self.w * 8)) / 2
self.y = (self.screenHeight - (self.h * 8)) / 2
for s in range(8):
for i in range(4):
if s % 2 == 0:
self.spriteB.append(
pyglet.sprite.Sprite(self.blackP, i * 2 * self.w + self.x + self.w, s * self.h + self.y))
self.spriteW.append(
pyglet.sprite.Sprite(self.whiteP, i * 2 * self.w + self.x + self.w, s * self.h + self.y))
else:
self.spriteB.append(
pyglet.sprite.Sprite(self.blackP, i * 2 * self.w + self.x, s * self.h + self.y))
self.spriteW.append(
pyglet.sprite.Sprite(self.whiteP, i * 2 * self.w + self.x, s * self.h + self.y))
for j in range(12,32):
self.spriteW[j].visible = False
for j in range(0,20):
self.spriteB[j].visible = False
def on_draw(self):
self.clear()
for s in range(8):
for i in range(4):
if s % 2 == 0:
self.blue.blit(i * 2 * self.w + self.x, s * self.h + self.y)
self.red.blit(i * 2 * self.w + self.x + self.w, s * self.h + self.y)
else:
self.blue.blit(i * 2 * self.w + self.x + self.w, s * self.h + self.y)
self.red.blit(i * 2 * self.w + self.x, s * self.h + self.y)
for i in range(32):
self.spriteW[i].draw()
self.spriteB[i].draw()
mygame=checkers()
pyglet.app.run()
My question maybe very vague or not specific but help needed please.

Related

Earth pulling Sun in 2d Physics Engine

I'm creating a basic physics engine in python and I've managed to create a simple "planet" class to handle the maths. I've also created a basic working scenario when a small planet orbits a larger one - if the small planet has zero mass. However, when I give the small planet any mass it slowly pulls the sun to the right in an arc shape. It's easier to see in this image:
.
I understand what's going on - the earth is pulling the sun right on one side and stopping it but not pulling it back on the other - but I have no idea how to fix it, short of giving the sun a hard-coded velocity. I've checked a few other sources but nothing helps - in fact this physics sim has the same problem (uncheck system centered).
Does this happen in the real world, or is it a glitch with this type of simulation? Either way, is there some sort of hack to prevent this from happening?
My planet class (all the methods are pretty straightforward):
import math
G = 6
class Planet():
def __init__(self, x = 0, y = 0, vx = 0, vy = 0, mass = 1, radius = 1, colour = "#ffffff"):
self.x = x
self.y = y
self.vx = vx
self.vy = vy
self.mass = mass
self.radius = radius
self.colour = colour
def draw(self, canvas):
canvas.create_oval(self.x - self.radius, self.y - self.radius, self.x + self.radius, self.y + self.radius, fill = self.colour)
def move_next(self):
self.x += self.vx
self.y += self.vy
def apply_gravity(self, other):
if other is self: #make sure you're not checking against yourself.
return 1
x = other.x - self.x
y = other.y - self.y
r = math.hypot(x, y)
if r == 0: #make sure they're not on each other.
return 1
gravity = G * (other.mass) / (r ** 2) #calculate the force that needs to be applied
self.vx += (x / r) * gravity #normalise the x component of vector and multiply it by the force
self.vy += (y / r) * gravity #normalise the y component of vector and multiply it by the force
And the "main" file:
from tkinter import *
import time
import planet
FPS = 1/60
window = Tk()
canvas = Canvas(window, width = 640, height = 400, bg = "#330033")
canvas.pack()
earth = planet.Planet(x = 320, y = 100, vx = 10, mass = 1, radius = 10, colour = "lightblue") #Because the earth's mass is so low, it won't be AS noticable, but it still pulls the sun a few pixels per rotation.
sun = planet.Planet(x = 320, y = 200, mass = 2e3, radius = 20, colour = "yellow")
planets = [earth, sun]
while True:
canvas.delete(ALL)
for planet in planets:
for other in planets:
planet.apply_gravity(other)
planet.move_next()
planet.draw(canvas)
window.update()
time.sleep(FPS)

pygame bullet physics messed up by scrolling

the code below is the bullet class for my shooter game in pygame. as you can see if you run the full game (https://github.com/hailfire006/economy_game/blob/master/shooter_game.py) the code works great to fire bullets at the cursor as long as the player isn't moving. However, I recently added scrolling, where I change a global offsetx and offsety every time the player gets close to an edge. These offsets are then used to draw each object in their respective draw functions.
unfortunately, my bullet physics in the bullet's init function no longer work as soon as the player scrolls and the offsets are added. Why are the offsets messing up my math and how can I change the code to get the bullets to fire in the right direction?
class Bullet:
def __init__(self,mouse,player):
self.exists = True
centerx = (player.x + player.width/2)
centery = (player.y + player.height/2)
self.x = centerx
self.y = centery
self.launch_point = (self.x,self.y)
self.width = 20
self.height = 20
self.name = "bullet"
self.speed = 5
self.rect = None
self.mouse = mouse
self.dx,self.dy = self.mouse
distance = [self.dx - self.x, self.dy - self.y]
norm = math.sqrt(distance[0] ** 2 + distance[1] ** 2)
direction = [distance[0] / norm, distance[1] / norm]
self.bullet_vector = [direction[0] * self.speed, direction[1] * self.speed]
def move(self):
self.x += self.bullet_vector[0]
self.y += self.bullet_vector[1]
def draw(self):
make_bullet_trail(self,self.launch_point)
self.rect = pygame.Rect((self.x + offsetx,self.y + offsety),(self.width,self.height))
pygame.draw.rect(screen,(255,0,40),self.rect)
You don't take the offset into account when calculating the angle between the player and the mouse. You can fix this by changing the distance like this:
distance = [self.dx - self.x - offsetx, self.dy - self.y - offsety]

Lennard Jones interaction between particles. Particles moving to one point

import numpy as np
import random
import pygame
background_colour = (255,255,255)
width, height = 300, 325
eps = 1
sigma = 1
dt = 0.05
class Particle():
def __init__(self):
self.x = random.uniform(0,400)
self.y = random.uniform(0,500)
self.vx = random.uniform(-.1,.1)
self.vy = random.uniform(-.1,.1)
self.fx = 0
self.fy = 0
self.m = 1
self.size = 10
self.colour = (0, 0, 255)
self.thickness = 0
def bounce(self):
if self.x > width - self.size:
self.x = 2*(width - self.size) - self.x
elif self.x < self.size:
self.x = 2*self.size - self.x
if self.y > height - self.size:
self.y = 2*(height - self.size) - self.y
elif self.y < self.size:
self.y = 2*self.size - self.y
def getForce(self, p2):
dx = self.x - p2.x
dy = self.y - p2.y
self.fx = 500*(-8*eps*((3*sigma**6*dx/(dx**2+dy**2)**4 - 6*sigma**12*dx/(dx**2+dy**2)**7)))
self.fy = 500*(-8*eps*((3*sigma**6*dy/(dx**2+dy**2)**4 - 6*sigma**12*dy/(dx**2+dy**2)**7)))
return self.fx, self.fy
def verletUpdate(self,dt):
self.x = self.x + dt*self.vx+0.5*dt**2*self.fx/self.m
self.y = self.y + dt*self.vy+0.5*dt**2*self.fy/self.m
def display(self):
pygame.draw.circle(screen, self.colour, (int(self.x), int(self.y)), self.size, self.thickness)
screen = pygame.display.set_mode((width, height))
screen.fill(background_colour)
partList = []
for k in range(10):
partList.append(Particle())
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
screen.fill(background_colour)
for k, particle in enumerate(partList):
for p2 in partList[k+1:]:
particle.getForce(p2)
particle.verletUpdate(dt)
particle.bounce()
particle.display()
pygame.display.flip()
pygame.quit()
Is my code correct? I tried to simulate particles in 2D move with Lennard Jones forces. I think calculating forces works okay but why my particles are moving to one point? Ocasionally I also get error OverflowError: Python int too large to convert to C long Any advice would be useful.
I can not comment on the physics of the simulation, but as far as the display is concerned following are my observations:
Your particles move to one point because the update condition for the x and y parameter in your code in verletUpdate are slowly moving to values beyond the display area. Also to values out of the range of the int() function which is causing your error. You can see this with the statement:
def verletUpdate(self,dt):
self.x = self.x + dt*self.vx+0.5*dt**2*self.fx/self.m
self.y = self.y + dt*self.vy+0.5*dt**2*self.fy/self.m
print self.x
print self.y
Sample Output:
290.034892392
9.98686293664
290.028208837
9.99352484332
-2.55451579742e+19
1.12437640586e+19
Also they saturate and with iterations, the update gets smaller and smaller:
def display(self):
print ' %s + %s '%(self.x,self.y)
pygame.draw.circle(screen, self.colour, (int(self.x), int(self.y)), self.size, self.thickness)
Output:
10.0009120033 + 10.0042647307
10.0009163718 + 10.0000322065
10.0009120033 + 10.0042647307
10.0009163718 + 10.0000322065
...
10.0009163718 + 10.0000322065
10.0009120033 + 10.0042647307
10.0009163718 + 10.0000322065
This is also why your bounce functions and your limit checking is not working. And after a lot of iterations on occasion your self.x and self.y are far exceeding the limits of int().
The code seems fine, but you can get rid of the overflow error by adding some checks above the draw line. For instance I initialized them randomly again to simulate a particle going off screen and us tracking a new one. Feel free to change it.
def display(self):
if(self.x<0 or self.x>height):
self.__init__()
print "reset"
if(self.y<0 or self.y>width):
self.__init__()
print "reset"
print ' %s + %s '%(self.x,self.y)
pygame.draw.circle(screen, self.colour, (int(self.x), int(self.y)), self.size, self.thickness)
Also at one point you adress the array as [k+1:], and addressing the zero element caused a divide by zero error. You might want to look at that.

Rotation matrix scales down

I'm trying to build some micro "3d engine" as to understand the basics of this field.
Everything works quite fine except for rotations. I use the standard rotation matrices to do this, yet all 3 of the possible rotations not only rotate the points, they also scale them down. This behaviour is not intended or wished for.
Following is the relevant part of the code (I think):
class Point:
def __init__(self, x, y, z, ui):
self.x = mpf(x)
self.y = mpf(y)
self.z = mpf(z)
self.ui = ui
def subtractVectorFromPoint(self, vector):
self.x -= vector.x
self.y -= vector.y
self.z -= vector.z
return self
def subtractPointFromPoint(self, point):
TempVector = Vector(0, 0, 0)
TempVector.x = self.x - point.x
TempVector.y = self.y - point.y
TempVector.z = self.z - point.z
return TempVector
def setPointToPoint(self, point):
self.x = point.x
self.y = point.y
self.z = point.z
return self
class Vector:
def __init__(self, x, y ,z):
self.x = mpf(x)
self.y = mpf(y)
self.z = mpf(z)
def rotateXY(self, degrees):
radians = mpf(math.radians(degrees))
self.x = (math.cos(radians) * self.x) + (- math.sin(radians) * self.y)
self.y = (math.sin(radians) * self.x) + (math.cos(radians) * self.y)
return self
#rotate xy plane by 15 degrees on pressing r
if event.key == pygame.K_r:
origin = Vector(0, 0, 0)
UI.draw_background()
for point in pointList:
tempVector = point.subtractPointFromPoint(origin)
point.setPointToPoint(origin)
point.addVectorToPoint(tempVector.rotateXY(15))
point.drawPoint()
That should be all you need I think. Any pointers to where I went wrong are welcome.
I know the classes miss an indent in the example here, I suck at the layout on this website :)
p.s. I tried using the "mpf()" function to increase the precision but this had 0 result.
The problem is in this part:
def rotateXY(self, degrees):
radians = mpf(math.radians(degrees))
self.x = (math.cos(radians) * self.x) + (- math.sin(radians) * self.y)
self.y = (math.sin(radians) * self.x) + (math.cos(radians) * self.y)
return self
self.y is being calculated using a self.x that is already adjusted, resulting in given problem.
A fix for this is using a temp variable like this:
def rotateXY(self, degrees):
radians = mpf(math.radians(degrees))
tempX = (math.cos(radians) * self.x) + (- math.sin(radians) * self.y)
self.y = (math.sin(radians) * self.x) + (math.cos(radians) * self.y)
self.x = tempX
return self

Colision Resolution between Circles - Slow Sliding

I am having trouble with circle to circle collision resolution.
First, i detect the collision, then if the balls collide, i separate them by the sum of their radii and set the velocities. That's easy.
My problem is when gravity is acting and a ball collides with another ball from above. It's suposed to bouce off but instead it slides very slowly until it drops in the ground.
Whats hapning is that afer the colision resolution, gravity pushes the ball down and causes another colision. I've tried separating the ball by the sum of their radii + x but it just slides a little faster.
You can watch the video at http://www.youtube.com/watch?v=tk7qQ9KDFp0&feature=youtu.be.
And here's the code that hadles colision:
for p in world.particle_list:
if not p == self:
if self.pos.sub(p.pos).get_length() <= self.radius * ppm + p.radius * ppm:
p_mass_ratio = float(self.mass) / (self.mass + p.mass)
self_mass_ratio = float(p.mass) / (self.mass + p.mass)
rel_pos = p.pos.sub(self.pos)
shift = rel_pos.set_length(- rel_pos.get_length() + self.radius * ppm + p.radius * ppm)
p.pos = p.pos.add(shift.scale(0.50))
self.pos = self.pos.add(shift.scale(-0.50))
p_speed = p.speed
self_speed = self.speed
self.speed = p_speed.add(self.speed.norm_reflect(rel_pos.set_angle(rel_pos.get_angle() + 90).scale(-self.friction))).scale(0.50 * self_mass_ratio)
p.speed = self_speed.add(p.speed.norm_reflect(rel_pos.set_angle(rel_pos.get_angle() + 90).scale(self.friction))).scale(0.50 * p_mass_ratio)
I made a vector class to handle this:
def dcos(x):
return cos(radians(x))
def dsin(x):
return sin(radians(x))
def dtan(x):
return tan(radians(x))
class Vec(object):
def __init__(self, x, y):
self.x = float(x)
self.y = float(y)
self.length = self.get_length()
self.angle = self.get_angle()
def get_length(self):
return sqrt(self.x ** 2 + self.y ** 2)
def get_angle(self):
return atan2(self.y, self.x) * 180 / pi
def add(self, vec1):
new_x = self.x + vec1.x
new_y = self.y + vec1.y
return Vec(new_x, new_y)
def sub(self, vec1):
new_x = self.x - vec1.x
new_y = self.y - vec1.y
return Vec(new_x, new_y)
def scale(self, k):
return Vec(self.x * k, self.y * k)
def set_angle(self, a):
new_x = self.length * dcos(a)
new_y = self.length * dsin(a)
if a == -90 or a == 90:
new_x = 0
if a == 180 or a == 0 or a == -180:
new_y = 0
return Vec(new_x, new_y)
def set_length(self, l):
new_x = l * dcos(self.angle)
new_y = l * dsin(self.angle)
return Vec(new_x, new_y)
def inverse(self):
return Vec(- self.x, - self.y)
def norm_reflect(self, vec1):
if self.get_angle == vec1.get_angle():
return Vec(self.x, self.y)
if vec1.get_angle() >= 0:
return self.set_angle(vec1.get_angle() - self.get_angle() + 90)
else:
return self.set_angle(vec1.get_angle() - self.get_angle() - 90)
(I don't know python, but I know physics and you aren't getting other answers so I'll take a crack at it.)
Look at
if self.pos.sub(p.pos).get_length() <= self.radius * ppm + p.radius * ppm:
...
rel_pos = p.pos.sub(self.pos)
shift = rel_pos.set_length(- rel_pos.get_length() + self.radius * ppm + p.radius * ppm)
p.pos = p.pos.add(shift.scale(0.50))
self.pos = self.pos.add(shift.scale(-0.50))
You're setting the length to a negative number, so you're moving the objects toward each other.
The norm_reflect() function doesn't make much sense, and I suspect it does something other than what you intend (in which case you're not testing your code).
These two lines:
self.speed = p_speed.add(self.speed.norm_reflect(rel_pos.set_angle(rel_pos.get_angle() + 90).scale(-self.friction))).scale(0.50 * self_mass_ratio)
p.speed = self_speed.add(p.speed.norm_reflect(rel_pos.set_angle(rel_pos.get_angle() + 90).scale(self.friction))).scale(0.50 * p_mass_ratio)
seem to be invoking norm_reflect() with only one argument, and you're bringing friction and mass ratios into the picture before the simple case is working, and you're reusing rel_pos after multiple transformations, and the physics is non-Newtonian (i.e. wrong enough to require starting over from a blank slate).

Categories