Files in Lua program not able to reference each other's variables - oop

I'm hoping somebody experienced can point out where/if I am missing some crucial syntax.
My program works fine (because 95% of it was created by a CS50 professor), with one exception - I cannot seem to get the player and flag files/classes to reference each other to show that my Mario character has reached the final flag.
Specifically, the function "Flag:victory(player)" does not appear to be pulling information from the player file/class, while player has a similar function that is able to access Flag, although I don't see any difference between the two files as to why Flag is not behaving properly.
Flag = Class{}
function Flag:init(map)
-- reference to map for checking tiles
self.texture = map.spritesheet
-- animation frames
self.frames = {}
-- current animation frame
self.currentFrame = nil
self.player = Player(map)
-- used to determine behavior and animations
self.state = 'waving'
-- x and y velocity
self.dy = 0
-- position on top of map tiles
self.y = map.tileHeight * ((map.mapHeight / 2) - 4)
self.x = (map.mapWidth - 3) * map.tileWidth
-- initialize all player animations
self.animations = {
['waving'] = Animation({
texture = self.texture,
frames = {
love.graphics.newQuad(0, 48, 16, 16, self.texture:getDimensions()),
love.graphics.newQuad(16, 48, 16, 16, self.texture:getDimensions()),
love.graphics.newQuad(0, 48, 16, 16, self.texture:getDimensions()),
},
interval = 0.30
}),
['falling'] = Animation({
texture = self.texture,
frames = {
love.graphics.newQuad(32, 48, 16, 16, self.texture:getDimensions())
}
})
}
-- initialize animation and current frame we should render
self.animation = self.animations['waving']
self.currentFrame = self.animation:getCurrentFrame()
end
function Flag:update(dt)
self.animation:update(dt)
self.currentFrame = self.animation:getCurrentFrame()
self:victory()
end
function Flag:render()
local scaleX = - 1
-- draw sprite with scale factor and offsets
love.graphics.draw(self.texture, self.currentFrame, math.floor(self.x + 8 / 2),
math.floor(self.y + 8 / 2), 0, scaleX, 1, 8 / 2, 8 / 2)
end
function Flag:victory(player)
if self.player.victory == true then -- when player reaches flag
self.state = 'falling' -- change flag animation to down sprite
self.animation = self.animations['falling']
self.y = self.y + 2 -- descend the flag
end
end
--[[
Represents our player in the game, with its own sprite.
]]
Player = Class{}
local WALKING_SPEED = 140
local JUMP_VELOCITY = 400
function Player:init(map)
self.x = 0
self.y = 0
self.width = 16
self.height = 20
-- offset from top left to center to support sprite flipping
self.xOffset = 8
self.yOffset = 10
-- reference to map for checking tiles
self.map = map -- just a convenience because map comes in as a param/arg so the self should be dropped
self.texture = love.graphics.newImage('graphics/blue_alien.png')
-- sound effects
self.sounds = {
['jump'] = love.audio.newSource('sounds/jump.wav', 'static'),
['hit'] = love.audio.newSource('sounds/hit.wav', 'static'),
['coin'] = love.audio.newSource('sounds/coin.wav', 'static'),
}
-- variable for playing sound just once when game ends
self.musicplayed = false
-- animation frames
self.frames = {}
-- current animation frame
self.currentFrame = nil
-- used to determine behavior and animations
self.state = 'idle'
-- determines sprite flipping
self.direction = 'left'
-- x and y velocity
self.dx = 0
self.dy = 0
-- position on top of map tiles
self.y = map.tileHeight * ((map.mapHeight - 2) / 2) - self.height
self.x = map.tileWidth * 10
self.xmax = self.x -- farthest that mario has ever gone to the right
self.xmin = 1 -- farthest mario may go to the left, based on xmax and left border of map
-- initialize all player animations
self.animations = {
['idle'] = Animation({
texture = self.texture,
frames = {
love.graphics.newQuad(0, 0, 16, 20, self.texture:getDimensions())
}
}),
['walking'] = Animation({
texture = self.texture,
frames = {
love.graphics.newQuad(128, 0, 16, 20, self.texture:getDimensions()),
love.graphics.newQuad(144, 0, 16, 20, self.texture:getDimensions()),
love.graphics.newQuad(160, 0, 16, 20, self.texture:getDimensions()),
love.graphics.newQuad(144, 0, 16, 20, self.texture:getDimensions()),
},
interval = 0.15
}),
['jumping'] = Animation({
texture = self.texture,
frames = {
love.graphics.newQuad(32, 0, 16, 20, self.texture:getDimensions())
}
}),
['victory'] = Animation({
texture = self.texture,
frames = {
love.graphics.newQuad(0, 0, 16, 20, self.texture:getDimensions()),
love.graphics.newQuad(48, 0, 16, 20, self.texture:getDimensions()),
love.graphics.newQuad(0, 0, 16, 20, self.texture:getDimensions()),
love.graphics.newQuad(160, 0, 16, 20, self.texture:getDimensions()),
love.graphics.newQuad(0, 0, 16, 20, self.texture:getDimensions()),
},
interval = .25
})
}
-- initialize animation and current frame we should render
self.animation = self.animations['idle']
self.currentFrame = self.animation:getCurrentFrame()
-- behavior map we can call based on player state
self.behaviors = {
['idle'] = function(dt)
-- add spacebar functionality to trigger jump state
if love.keyboard.wasPressed('space') then
self.dy = -JUMP_VELOCITY
self.state = 'jumping'
self.animation = self.animations['jumping']
self.sounds['jump']:play()
elseif love.keyboard.isDown('left') then
self.direction = 'left'
self.dx = -WALKING_SPEED
self.state = 'walking'
self.animations['walking']:restart()
self.animation = self.animations['walking']
self:checkLeftBoundary()
elseif love.keyboard.isDown('right') then
self.direction = 'right'
self.dx = WALKING_SPEED
self.state = 'walking'
self.animations['walking']:restart()
self.animation = self.animations['walking']
else
self.dx = 0
end
self:checkLeftBoundary()
self:checkRightBoundary()
end,
['walking'] = function(dt)
-- keep track of input to switch movement while walking, or reset
-- to idle if we're not moving
if love.keyboard.wasPressed('space') then
self.dy = -JUMP_VELOCITY
self.state = 'jumping'
self.animation = self.animations['jumping']
self.sounds['jump']:play()
elseif love.keyboard.isDown('left') then
self.direction = 'left'
self.dx = -WALKING_SPEED
elseif love.keyboard.isDown('right') then
self.direction = 'right'
self.dx = WALKING_SPEED
else
self.dx = 0
self.state = 'idle'
self.animation = self.animations['idle']
end
self:checkLeftBoundary()
self:checkRightBoundary()
-- check for collisions moving left and right
self:checkRightCollision()
self:checkLeftCollision()
-- check if there's a tile directly beneath us
if not self.map:collides(self.map:tileAt(self.x, self.y + self.height)) and
not self.map:collides(self.map:tileAt(self.x + self.width - 1, self.y + self.height)) then
-- if so, reset velocity and position and change state
self.state = 'jumping'
self.animation = self.animations['jumping']
end
end,
['jumping'] = function(dt)
if love.keyboard.isDown('left') then
self.direction = 'left'
self.dx = -WALKING_SPEED
elseif love.keyboard.isDown('right') then
self.direction = 'right'
self.dx = WALKING_SPEED
end
-- apply map's gravity before y velocity
self.dy = self.dy + self.map.gravity
-- check if there's a tile directly beneath us
if self.map:collides(self.map:tileAt(self.x, self.y + self.height)) or
self.map:collides(self.map:tileAt(self.x + self.width - 1, self.y + self.height)) then
-- if so, reset velocity and position and change state
self.dy = 0
self.state = 'idle'
self.animation = self.animations['idle']
self.y = (self.map:tileAt(self.x, self.y + self.height).y - 1) * self.map.tileHeight - self.height
end
self:checkLeftBoundary()
self:checkRightBoundary()
-- check for collisions moving left and right
self:checkRightCollision()
self:checkLeftCollision()
end,
['victory'] = function(dt)
self.dx = 0
-- check if there's a tile directly beneath us
if self.map:collides(self.map:tileAt(self.x, self.y + self.height)) or
self.map:collides(self.map:tileAt(self.x + self.width - 1, self.y + self.height)) then
-- if so, reset velocity and position and change state
self.dy = 0
self.y = (self.map:tileAt(self.x, self.y + self.height).y - 1) * self.map.tileHeight - self.height
end
end
}
end
function Player:update(dt)
self.behaviors[self.state](dt)
self.animation:update(dt)
self.currentFrame = self.animation:getCurrentFrame()
self.x = self.x + self.dx * dt
self.xmax = math.max(self.x, self.xmax) -- tester to update xmax if player moves further to right than ever before
self.xmin = math.max(1, math.min(self.xmax - VIRTUAL_WIDTH / 2, map.mapWidthPixels - VIRTUAL_WIDTH)) -- farthest mario may go to the left, based on xmax and left border of map
self:calculateJumps()
self:gameover()
self:reachflag()
if self.map:victory() == true then
self.victory = true
end
-- apply velocity
self.y = self.y + self.dy * dt
end
function Player:gameover()
if self.y > 300 then
self.game_over = true
end
end
function Player:reachflag(Flag)
if self.x >= flag.x then
self.victory = true
end
end
-- jumping and block hitting logic
function Player:calculateJumps()
-- if we have negative y velocity (jumping), check if we collide
-- with any blocks above us
if self.dy < 0 then
if self.map:tileAt(self.x, self.y).id ~= TILE_EMPTY or
self.map:tileAt(self.x + self.width - 1, self.y).id ~= TILE_EMPTY then
-- reset y velocity
self.dy = 0
-- change block to different block
local playCoin = false
local playHit = false
if self.map:tileAt(self.x, self.y).id == JUMP_BLOCK then
self.map:setTile(math.floor(self.x / self.map.tileWidth) + 1,
math.floor(self.y / self.map.tileHeight) + 1, JUMP_BLOCK_HIT)
playCoin = true
else
playHit = true
end
if self.map:tileAt(self.x + self.width - 1, self.y).id == JUMP_BLOCK then
self.map:setTile(math.floor((self.x + self.width - 1) / self.map.tileWidth) + 1,
math.floor(self.y / self.map.tileHeight) + 1, JUMP_BLOCK_HIT)
playCoin = true
else
playHit = true
end
if playCoin then
self.sounds['coin']:play()
elseif playHit then
self.sounds['hit']:play()
end
end
end
end
-- checks two tiles to our left to see if a collision occurred
function Player:checkLeftCollision()
if self.dx < 0 then
-- check if there's a tile directly beneath us
if self.map:collides(self.map:tileAt(self.x - 1, self.y)) or
self.map:collides(self.map:tileAt(self.x - 1, self.y + self.height - 1)) then
-- if so, reset velocity and position and change state
self.dx = 0
self.x = self.map:tileAt(self.x - 1, self.y).x * self.map.tileWidth
end
end
end
-- checks two tiles to our right to see if a collision occurred
function Player:checkRightCollision()
if self.dx > 0 then
-- check if there's a tile directly beneath us
if self.map:collides(map:tileAt(self.x + self.width, self.y)) or
self.map:collides(map:tileAt(self.x + self.width, self.y + self.height - 1)) then
-- if so, reset velocity and position and change state
self.dx = 0
self.x = (self.map:tileAt(self.x + self.width, self.y).x - 1) * map.tileWidth - self.width
end
end
end
function Player:checkLeftBoundary()
if self.x <= self.xmin then -- went too far left
self.x = self.xmin
if self.direction == 'left'then
self.dx = 0 -- set speed to zero but keep state, ie walking, jumping/falling
end
end
end
function Player:checkRightBoundary()
if self.x >= map.mapWidthPixels - 16 then -- went too far right
self.x = map.mapWidthPixels - 16
if self.direction == 'right'then
self.dx = 0 -- set speed to zero but keep state, ie walking, jumping/falling
end
end
end
function Player:render()
local scaleX
-- set negative x scale factor if facing left, which will flip the sprite
-- when applied
if self.direction == 'right' then
scaleX = 1
else
scaleX = -1
end
-- draw sprite with scale factor and offsets
love.graphics.draw(self.texture, self.currentFrame, math.floor(self.x + self.xOffset),
math.floor(self.y + self.yOffset), 0, scaleX, 1, self.xOffset, self.yOffset)
if self.game_over == true then
self.state = 'idle'
self.dy = 0
self.dx = 0
map.music:stop()
if self.musicplayed == false then
love.audio.newSource('sounds/Laser_Shoot2.wav', 'static'):play()
self.musicplayed = true
end
love.graphics.print('Oh Snap! Try again? (y/n)', self.xmin + 40, 40)
if love.keyboard.isDown('y') then
self.map:init()
self.map:render()
elseif love.keyboard.isDown('n')then
love.event.quit()
end
end
if self.victory == true then
self.state = 'victory'
self.animation = self.animations['victory']
if self.musicplayed == false then
love.audio.newSource('sounds/Powerup23.wav', 'static'):play()
self.musicplayed = true
end
love.graphics.print('Congratulations! Play again? (y/n)', self.xmin + 35, 40)
if love.keyboard.isDown('y') then
self.map:init()
self.map:render()
map.music:stop()
elseif love.keyboard.isDown('n')then
love.event.quit()
end
end
end
--[[
Super Mario Bros. Demo
Author: Colton Ogden
Original Credit: Nintendo
Demonstrates rendering a screen of tiles.
]]
Class = require 'class'
push = require 'push'
require 'Animation'
require 'Map'
require 'Player'
require 'Flag'
-- close resolution to NES but 16:9
VIRTUAL_WIDTH = 432
VIRTUAL_HEIGHT = 243
-- actual window resolution
WINDOW_WIDTH = 1280
WINDOW_HEIGHT = 720
-- seed RNG
math.randomseed(os.time())
-- makes upscaling look pixel-y instead of blurry
love.graphics.setDefaultFilter('nearest', 'nearest')
-- an object to contain our map data
map = Map()
flag = Flag(map)
player = Player(map)
-- performs initialization of all objects and data needed by program
function love.load()
-- sets up a different, better-looking retro font as our default
love.graphics.setFont(love.graphics.newFont('fonts/font.ttf', 16))
-- sets up virtual screen resolution for an authentic retro feel
push:setupScreen(VIRTUAL_WIDTH, VIRTUAL_HEIGHT, WINDOW_WIDTH, WINDOW_HEIGHT, {
fullscreen = false,
resizable = true
})
love.window.setTitle('Super Mario 50')
love.keyboard.keysPressed = {}
love.keyboard.keysReleased = {}
end
-- called whenever window is resized
function love.resize(w, h)
push:resize(w, h)
end
-- global key pressed function
function love.keyboard.wasPressed(key)
if (love.keyboard.keysPressed[key]) then
return true
else
return false
end
end
-- global key released function
function love.keyboard.wasReleased(key)
if (love.keyboard.keysReleased[key]) then
return true
else
return false
end
end
-- called whenever a key is pressed
function love.keypressed(key)
if key == 'escape' then
love.event.quit()
end
love.keyboard.keysPressed[key] = true
end
-- called whenever a key is released
function love.keyreleased(key)
love.keyboard.keysReleased[key] = true
end
-- called every frame, with dt passed in as delta in time since last frame
function love.update(dt)
map:update(dt)
-- reset all keys pressed and released this frame
love.keyboard.keysPressed = {}
love.keyboard.keysReleased = {}
end
-- called each frame, used to render to the screen
function love.draw()
-- begin virtual resolution drawing
push:apply('start')
-- clear screen using Mario background blue
love.graphics.clear(108/255, 140/255, 255/255, 255/255)
-- renders our map object onto the screen
love.graphics.translate(math.floor(-map.camX + 0.5), math.floor(-map.camY + 0.5))
map:render()
-- end virtual resolution
push:apply('end')
end
--[[
Contains tile data and necessary code for rendering a tile map to the
screen.
]]
require 'Util'
Map = Class{}
TILE_BRICK = 1
TILE_EMPTY = -1
-- cloud tiles
CLOUD_LEFT = 6
CLOUD_RIGHT = 7
-- bush tiles
BUSH_LEFT = 2
BUSH_RIGHT = 3
-- mushroom tiles
MUSHROOM_TOP = 10
MUSHROOM_BOTTOM = 11
-- jump block
JUMP_BLOCK = 5
JUMP_BLOCK_HIT = 9
-- flagpole
FLAGPOLE_TOP = 8
FLAGPOLE_MIDDLE = 12
FLAGPOLE_BOTTOM = 16
PYRAMID_BLOCK = 17
-- a speed to multiply delta time to scroll map; smooth value
local SCROLL_SPEED = 62
-- constructor for our map object
function Map:init()
self.spritesheet = love.graphics.newImage('graphics/spritesheet.png')
self.sprites = generateQuads(self.spritesheet, 16, 16)
self.music = love.audio.newSource('sounds/music.wav', 'static')
self.pyramid_block = love.graphics.newImage('graphics/pyramidblock.png')
self.tileWidth = 16
self.tileHeight = 16
self.mapWidth = 300
self.mapHeight = 28
self.tiles = {}
-- applies positive Y influence on anything affected
self.gravity = 15
-- associate player with map
self.player = Player(self)
self.flag = Flag(self)
-- camera offsets
self.camX = 0
self.camY = -3
-- cache width and height of map in pixels
self.mapWidthPixels = self.mapWidth * self.tileWidth
self.mapHeightPixels = self.mapHeight * self.tileHeight
-- first, fill map with empty tiles
for y = 1, self.mapHeight do
for x = 1, self.mapWidth do
-- support for multiple sheets per tile; storing tiles as tables
self:setTile(x, y, TILE_EMPTY)
end
end
-- begin generating the terrain using vertical scan lines
local x = 1
while x < self.mapWidth - 20 do
-- 2% chance to generate a cloud
-- make sure we're 2 tiles from edge at least
if x < self.mapWidth - 2 then
if math.random(20) == 1 then
-- choose a random vertical spot above where blocks/pipes generate
local cloudStart = math.random(self.mapHeight / 2 - 6)
self:setTile(x, cloudStart, CLOUD_LEFT)
self:setTile(x + 1, cloudStart, CLOUD_RIGHT)
end
end
-- 5% chance to generate a mushroom
if math.random(20) == 1 then
-- left side of pipe
self:setTile(x, self.mapHeight / 2 - 2, MUSHROOM_TOP)
self:setTile(x, self.mapHeight / 2 - 1, MUSHROOM_BOTTOM)
-- creates column of tiles going to bottom of map
for y = self.mapHeight / 2, self.mapHeight do
self:setTile(x, y, TILE_BRICK)
end
-- next vertical scan line
x = x + 1
-- 10% chance to generate a bush, being sure to generate away from edge
elseif math.random(10) == 1 and x < self.mapWidth - 3 then
local bushLevel = self.mapHeight / 2 - 1
-- place bush component and then column of bricks
self:setTile(x, bushLevel, BUSH_LEFT)
for y = self.mapHeight / 2, self.mapHeight do
self:setTile(x, y, TILE_BRICK)
end
x = x + 1
self:setTile(x, bushLevel, BUSH_RIGHT)
for y = self.mapHeight / 2, self.mapHeight do
self:setTile(x, y, TILE_BRICK)
end
x = x + 1
-- 10% chance to not generate anything, creating a gap
elseif math.random(10) ~= 1 then
-- creates column of tiles going to bottom of map
for y = self.mapHeight / 2, self.mapHeight do
self:setTile(x, y, TILE_BRICK)
end
-- chance to create a block for Mario to hit
if math.random(15) == 1 then
self:setTile(x, self.mapHeight / 2 - 4, JUMP_BLOCK)
end
-- next vertical scan line
x = x + 1
else
-- increment X so we skip two scanlines, creating a 2-tile gap
x = x + 2
end
end
while x <= self.mapWidth do
-- draw in pyramid
if x == self.mapWidth - 13 then
local row = 1 -- how wide pyramid to be
while row < 7 do
local column = 1 -- might need to not say local everytime
while column <= row do
self:setTile(x, self.mapHeight / 2 - column, PYRAMID_BLOCK)
column = column + 1
end
-- creates column of tiles going to bottom of map
for y = self.mapHeight / 2, self.mapHeight do
self:setTile(x, y, TILE_BRICK)
end
row = row + 1
x = x + 1
end
end
-- draw in flagpole
if x == self.mapWidth - 2 then
self:setTile(x, self.mapHeight / 2 - 3, FLAGPOLE_TOP)
self:setTile(x, self.mapHeight / 2 - 2, FLAGPOLE_MIDDLE)
self:setTile(x, self.mapHeight / 2 - 1, FLAGPOLE_BOTTOM)
end
-- creates column of tiles going to bottom of map
for y = self.mapHeight / 2, self.mapHeight do
self:setTile(x, y, TILE_BRICK)
end
-- next vertical scan line
x = x + 1
end
-- start the background music
self.music:setLooping(true)
self.music:play()
end
-- return whether a given tile is collidable
function Map:collides(tile)
-- define our collidable tiles
local collidables = {
TILE_BRICK, JUMP_BLOCK, JUMP_BLOCK_HIT,
MUSHROOM_TOP, MUSHROOM_BOTTOM, PYRAMID_BLOCK
}
-- iterate and return true if our tile type matches
for _, v in ipairs(collidables) do
if tile.id == v then
return true
end
end
return false
end
-- this function doesn't appear to be doing anything...
function Map:victory(player, flag)
if self.player.x >= self.flag.x * map.tileWidth then
return true
else
return false
end
end
-- function to update camera offset with delta time
function Map:update(dt)
self.player:update(dt)
self.flag:update(dt)
-- keep camera's X coordinate following the player, preventing camera from
-- scrolling past 0 to the left and the map's width
self.camX = math.min(self.mapWidthPixels - VIRTUAL_WIDTH, math.max(self.camX, math.min(self.player.x - VIRTUAL_WIDTH / 2,
math.min(self.mapWidthPixels - VIRTUAL_WIDTH, self.player.x))))
end
-- gets the tile type at a given pixel coordinate
function Map:tileAt(x, y)
return {
x = math.floor(x / self.tileWidth) + 1,
y = math.floor(y / self.tileHeight) + 1,
id = self:getTile(math.floor(x / self.tileWidth) + 1, math.floor(y / self.tileHeight) + 1)
}
end
-- returns an integer value for the tile at a given x-y coordinate
function Map:getTile(x, y)
return self.tiles[(y - 1) * self.mapWidth + x]
end
-- sets a tile at a given x-y coordinate to an integer value
function Map:setTile(x, y, id)
self.tiles[(y - 1) * self.mapWidth + x] = id
end
-- renders our map to the screen, to be called by main's render
function Map:render()
for y = 1, self.mapHeight do
for x = 1, self.mapWidth do
local tile = self:getTile(x, y)
if tile ~= TILE_EMPTY then
if tile > 16 then
love.graphics.draw(self.pyramid_block,
(x - 1) * self.tileWidth, (y - 1) * self.tileHeight)
else
love.graphics.draw(self.spritesheet, self.sprites[tile],
(x - 1) * self.tileWidth, (y - 1) * self.tileHeight)
end
end
end
end
self.player:render()
self.flag:render()
end

You're using 'self.player' which is a brand new player at the init() (which is a different player than the one you want)
You need to use 'player' that you passed as an argument to check if player.victory is true.

Related

Update parameters of a function in a while loop

I am trying to execute a while loop that holds a function with parameters. However, I have noticed that the parameters inside the while loop are not updated which leads to an infinite while loop. Is there a reason behind the fact that the function parameters are not being updated after every loop?
import shapefile
from osgeo import gdal
#import rasterio
print (gdal.VersionInfo())
def pointInRect(x, y, x1, y1, w, h): # check if a raster point is in another raster
x2, y2 = x1+w, y1+h
if (x1 < x and x < x2):
if (y1 < y and y < y2):
return True
return False
# Open the shapes centroids
shp_cntrds = 'Path to centroids'
sf_cntrds = shapefile.Reader(shp_cntrds)
shapes_cntrds = sf_cntrds.shapes()
records_cntrds = sf_cntrds.records()
# adjust labels position according to its shapes centroids position
for i in range(len(records_cntrds)):
print(i)
tods = gdal.Open(str(records_cntrds[i][1]))
width = tods.RasterXSize
height = tods.RasterYSize
tods.SetGeoTransform([shapes_cntrds[i].points[0][0] - (width * 0.005), 0.01, 0,
shapes_cntrds[i].points[0][1] + (height * 0.005), 0, -0.01])
gt = tods.GetGeoTransform()
left = gt[0]
bottom = gt[3] + width * gt[4] + height * gt[5]
right = gt[0] + width * gt[1] + height * gt[2]
top = gt[3]
srs = osr.SpatialReference()
srs.SetUTM(32, 1) # set crs
srs.SetWellKnownGeogCS('WGS84') # set crs
tods.SetProjection(srs.ExportToWkt()) # set Projection and save file
print(width, height)
tods = None
# iterate through Labels and move labels away from each others if they overlapp
for i in range(len(records_cntrds)):
tods1 = gdal.Open(str(records_cntrds[i][1])) # records of the centroid shapefile contains the raster file path
width = tods1.RasterXSize
height = tods1.RasterYSize
gt = tods1.GetGeoTransform()
left = gt[0]
bottom = gt[3] + width * gt[4] + height * gt[5]
right = gt[0] + width * gt[1] + height * gt[2]
top = gt[3]
face = [x for x in list(range(len(records_cntrds))) if x != i]
tods1 = None
for j in face:
if str(records_cntrds[i][1]) == str(records_cntrds[j][1]):
pass
else:
ds_raster_face = gdal.Open(str(records_cntrds[j][1]))
#print(str(records_cntrds[i][1]))
#print(str(records_cntrds[j][1]))
gt_face = ds_raster_face.GetGeoTransform()
width_face = ds_raster_face.RasterXSize
height_face = ds_raster_face.RasterYSize
left_face = gt_face[0]
bottom_face = gt_face[3] + width_face * gt_face[4] + height_face * gt_face[5]
right_face = gt_face[0] + width_face * gt_face[1] + height_face * gt_face[2]
top_face = gt_face[3]
width1 = width
left1 = left
height1 = height
bottom1 = bottom
while pointInRect(left_face, bottom_face, left1, bottom1, width1*0.01, height1*0.01) :
tods2 = gdal.Open(str(records_cntrds[i][1]))
gt = tods2.GetGeoTransform()
width1 = tods2.RasterXSize
height1 = tods2.RasterYSize
left1 = gt[0]
bottom1 = gt[3] + width1 * gt[4] + height1 * gt[5]
print("while executed")
tods2.SetGeoTransform([(shapes_cntrds[i].points[0][0] - (width1 * 0.005)) - 2.7, 0.01, 0,
(shapes_cntrds[i].points[0][1] + (height1 * 0.005)) - 2.8, 0, -0.01])
print("coordinates changed to",(i, left1, bottom1, width1, height1))
tods2 = None
The while loop should break when the function return false but it is repeating the same thing. Are the gt values not updatet or are they initialized again ?

Pulp solves multiple combinatorial problems

As the title says,
I want to solve a problem similar to the summation of multiple schemes into a fixed constant, However, when I suggest the constrained optimization model, I can't get all the basic schemes well. Part of the opinion is to add a constraint when I get a solution. However, the added constraint leads to incomplete solution and no addition leads to a dead cycle.
Here is my problem description
I have a list of benchmark data detail_list ,My goal is to select several numbers from the benchmark data list(detail_list), but not all of them, so that the sum of these data can reach the sum of the number(plan_amount) I want.
For Examle
detail_list = [50, 100, 80, 40, 120, 25],
plan_amount = 20,
The feasible schemes are:
detail_list[2]=20 can be satisfied, detail_list[1](noly 10) + detail_list[3](only 10) = plan_amount(20) , detail_list[1](only 5) + detail_list[3](only 15) = plan_amount(20) also can be satisfied, and detail_list1 + detail_list2 + detail_list3 = plan_amount(20). But you can't take four elements in the detail_list are combined, because number = 3, indicating that a maximum of three elements are allowed to be combined.
from pulp import *
num = 6 # the list max length
number_max = 3 # How many combinations can there be at most
plan_amount = 20
detail_list = [50, 100, 80, 40, 120, 25] # Basic data
plan_model = LpProblem("plan_model")
alpha = [LpVariable("alpha_{0}".format(i+1), cat="Binary") for i in range(num)]
upBound_num = [int(detail_list_money) for detail_list_money in detail_list]
num_channel = [
LpVariable("fin_money_{0}".format(i+1), lowBound=0, upBound=upBound_num[i], cat="Integer") for i
in range(num)]
plan_model += lpSum(num_channel) == plan_amount
plan_model += lpSum(alpha) <= number_max
for i in range(num):
plan_model += num_channel[i] >= alpha[i] * 5
plan_model += num_channel[i] <= alpha[i] * detail_list[i]
plan_model.writeLP("2222.lp")
test_dd = open("2222.txt", "w", encoding="utf-8")
i = 0
while True:
plan_model.solve()
if LpStatus[plan_model.status] == "Optimal":
test_dd.write(str(i + 1) + "times result\n")
for v in plan_model.variables():
test_dd.write(v.name + "=" + str(v.varValue))
test_dd.write("\n")
test_dd.write("============================\n\n")
alpha_0_num = 0
alpha_1_num = 0
for alpha_value in alpha:
if value(alpha_value) == 0:
alpha_0_num += 1
if value(alpha_value) == 1:
alpha_1_num += 1
plan_model += (lpSum(
alpha[k] for k in range(num) if value(alpha[k]) == 1)) <= alpha_1_num - 1
plan_model.writeLP("2222.lp")
i += 1
else:
break
test_dd.close()
I don't know how to change my constraints to achieve this goal. Can you help me

I keep getting an error saying there is no picture when there is. What am I doing wrong?

def blendPictures(pict1, pict2, overlapAmt):
width1 = getWidth(pict1)
height1 = getHeight(pict1)
width2 = getWidth(pict2)
height2 = getHeight(pict2)
newWidth = width1 + width2 - overlapAmt
newHeight = min(height1, height2)
newCanvas = makeEmptyPicture(newWidth, newHeight)
for x in range(width1 - overlapAmt):
for y in range(newHeight):
color = getColor(getPixel(pict1, x, y))
setColor(getPixel(newCanvas, x, y), color)
pict2_x = 0
for pict1_x in range(width1 - overlapAmt, width1):
for y in range(newHeight):
pixel1 = getPixel(pict1, pict1_x, y)
pixel2 = getPixel(pict2, pict2_x, y)
newRed = 0.50 * getRed(pixel1) + 0.50 * getRed(pixel2)
newGreen = 0.50 * getGreen(pixel1) + 0.50 * getGreen(pixel2)
newBlue = 0.50 * getBlue(pixel1) + 0.50 * getBlue(pixel2)
color = makeColor(newRed, newGreen, newBlue)
setColor(getPixel(newCanvas, pict1_x, y), color)
pict2_x = pict2_x + 1
targetX = width1
for x in range(overlapAmt, width2):
for y in range(newHeight):
color = getColor(getPixel(pict2, x, y))
setColor(getPixel(newCanvas, targetX, y), color)
targetX = targetX + 1
return newCanvas
def swapBackground( src, background, newBackground ):
# src, and background must be the same size
# newBackground must be at least as big as src and background
for x in range(1, getWidth( src ) + 1 ) :
for y in range(1, getHeight( src ) + 1 ) :
srcPxl = getPixel( src, x, y )
backgroundPxl = getPixel( background, x, y )
if (distance(getColor( srcPxl ), getColor( backgroundPxl )) < 15.0):
setColor( srcPxl, getColor( getPixel( newBackground, x, y ) ) )
return src
jackalope = blendPictures('rabbit.jpg', 'antelope.jpg', 50)
writePictureTo(jackalope, "./jackalope.jpg")
#here swap the background to place your photo on front
swapBackground( 'photograph.jpg', 'jackalope.jpg', newBackground )
writePictureTo(newBackground, "./nexttojackalope.jpg")
swapBackground( 'rabbit.jpg', 'campus.jpg', newBackground1 )
writePictureTo(newBackground1, "./campustemp.jpg")
swapBackground( 'antelope.jpg', 'campustemp.jpg', newBackground2 )
writePictureTo(newBackground1, "./campusfinal.jpg")
Where the .jpg's are I put where the files will go or where they are pulling from. I have a picture of a rabbit and an antelope with a jackalope wav file and a picture of myself and a picture to put as the background. But I still get an error on line 2 saying that getWidth(picture) isn't defined and I'm not sure what to do. Any ideas?
In order to use the getWidth() function you need to pass a picture object as it's argument. So you will need to first create a picture object using the makePicture() function. For example:
pict1 = makePicture('rabbit.jpg')
width1 = getWidth1(pict1)
Here's a good guide on working with pictures in JES. http://www.cs.bu.edu/courses/cs101b1/jes/#Pictures%20and%20Sound

How do I set LinePlot line thickness and style? (DigitalMicrograph script)

The scripting help documentation of DigitalMicrograph offers an example for setting LinePlot styles with respect of colour and fill (see example script below).
However, the ImageDisplay menu for LinePlots also allows setting line styles (dotted, dashed,...) line thickness and transparency. Can somebody give an example on how to set these values, please?
// create image and image document
ImageDocument imageDoc = CreateImageDocument( "New ImageDocument" )
number width = 256
number height = 5
image img := RealImage("Line Plot Test", 4, width, height )
img = sin( irow + icol/100 )
// add LinePlotImageDisplay to ImageDocument
ImageDisplay imgdsp = imageDoc.ImageDocumentAddImageDisplay( img, 3 )
imgdsp.LinePlotImageDisplaySetContrastLimits( -1.1, 1.1 )
imgdsp.LinePlotImageDisplaySetDoAutoSurvey( 0, 0 )
// draw fill and line for slice 0
imgdsp.LinePlotImageDisplaySetSliceDrawingStyle(0, 3)
// set line color to red
imgdsp.LinePlotImageDisplaySetSliceComponentColor(0, 0, 1, 0, 0)
// set fill color to yellow
imgdsp.LinePlotImageDisplaySetSliceComponentColor(0, 1, 0.9, 0.9, 0)
// draw fill for slice 1 and 2
imgdsp.LinePlotImageDisplaySetSliceDrawingStyle(1, 2)
imgdsp.LinePlotImageDisplaySetSliceDrawingStyle(2, 2)
// draw line for slice 3 and 4
imgdsp.LinePlotImageDisplaySetSliceDrawingStyle(3, 1)
imgdsp.LinePlotImageDisplaySetSliceDrawingStyle(4, 1)
imageDoc.ImageDocumentShow()
The commands you are looking for are:
void LinePlotImageDisplaySetSliceLineThickness( LinePlotImageDisplay lpid, Number slice_id, Number lineThickness )
void LinePlotImageDisplaySetSliceLineStyle( LinePlotImageDisplay lpid, Number slice_id, Number lineStyle )
void LinePlotImageDisplaySetSliceTransparency( LinePlotImageDisplay lpid, Number sliceIndex, Boolean doTransparent, Number transparency )
They are demonstrated in the example below. Note that the visibility of line styles depend on the number of points in a LinePlot. If the LinePlot has more data points than displayed pixels, you may not notice the line style as it is defined 'in between' data points:
// create image and image document
ImageDocument imageDoc = CreateImageDocument( "New ImageDocument" )
number width = 64
number height = 10
image img := RealImage("Line Plot Test", 4, width, height )
img = sin( irow + icol / iwidth * 2 * Pi() ) + ( irow < ( height / 2 ) ? 1.5 : -1.5 )
// add LinePlotImageDisplay to ImageDocument
ImageDisplay imgdsp = imageDoc.ImageDocumentAddImageDisplay( img, 3 )
imgdsp.LinePlotImageDisplaySetContrastLimits( -2.6, 2.6 )
imgdsp.LinePlotImageDisplaySetDoAutoSurvey( 0, 0 )
// Line style demo
for ( number i = 0 ; i < height / 2 ; i++ )
{
number index = i + height / 2
// Set Line - drawing (no fill)
imgdsp.LinePlotImageDisplaySetSliceDrawingStyle( index , 1 )
// Set black line
imgdsp.LinePlotImageDisplaySetSliceComponentColor( index , 0 , 0, 0, 0 )
// Set LineThickness
imgdsp.LinePlotImageDisplaySetSliceLineThickness( index , height / 2 - i + 1 )
// Set LineStyle
imgdsp.LinePlotImageDisplaySetSliceLineStyle( index , i )
}
// Transparecny demo
for ( number i = 0 ; i < height / 2 ; i++ )
{
number index = i
// Set Fill & Line - drawing
imgdsp.LinePlotImageDisplaySetSliceDrawingStyle( index , 1 + 2 )
// Set black fill & red line
imgdsp.LinePlotImageDisplaySetSliceComponentColor( index , 1 , 0 , 0 , 0 )
imgdsp.LinePlotImageDisplaySetSliceComponentColor( index , 0 , 255 , 0 , 0 )
// Set transparency ( 70% transparency = 30% opacity )
imgdsp.LinePlotImageDisplaySetSliceTransparency( index , 1 , 0.7 )
}
imageDoc.ImageDocumentShow()

Repeating 2 backgrounds in Corona SDK

Here's a problem: I'm making a simple physics game using Corona SDK and very simple module: http://developer.coronalabs.com/code/move-camera So I've got fish object with physics body and in each frame (enterFrame event) I'm centering camera on it
camera.x = -fish.x + screenWidth / 2
And I've got two backgrounds bg1 and bg2, which tiled each after other (bg1 bg2 bg1 bg2 etc) will make nice moving-world effect without user knowing that there are only 2 backgrounds. The problem is I can't get right calculations of their positions to make such effect. I googled a lot, but can't find anything to fit my needs.
Here's a free art, which I'm using http://www.vickiwenderlich.com/2013/02/free-game-art-flying-goldfish/ There you can find these two backgrounds.
It's also possible that fish can go slightly in opposite direction (generally it's moving to the right so to make world-moving effect backgrounds has to move to the left) so it would be nice if it'll in calculations.
I figured out something like this (however it doesn't work but maybe I'm close):
local function updateFrame(event)
local m
local dfx = lfx - fish.x
lfx = fish.x
camera.x = -fish.x + screenWidth / 2
--print("dfx = " .. dfx)
bg1.x = bg1.x + dfx
bg2.x = bg2.x + dfx
s = s + dfx
if mAbs(s) > screenWidth then
m = sgn(s)
if m ~= 0 then
s = s - m * screenWidth
if m < 0 then
bg1.x = bg1.x - 2 * m * screenWidth
else
bg2.x = bg2.x - 2 * m * screenWidth
end
end
end
end
Runtime:addEventListener( "enterFrame", updateFrame );
s = screenLeft - screenWidth
where s is the sum of pixels moved and if it's over screenWidth I jump with one of the backgrounds, lfx is the last fish x location, dfx is a difference between last and current fish location and that's it.
If you can help me with my calculations or give me new ones or just give some interesting links please write them right here.
Any help will be appreciated,
Regards
local road = display.newImageRect( "Images/roadBg1.png",2247/4,559/4 )
road:setReferencePoint( display.CenterLeftReferencePoint )
road.x = 0
road.y = baseline - 20
local road2 = display.newImageRect( "Images/roadBg1.png",2247/4,559/4 )
road2:setReferencePoint( display.CenterLeftReferencePoint )
road2.x = 2247/4
road2.y = baseline - 20
local tPrevious = system.getTimer()
local function move(event)
local tDelta = event.time - tPrevious
tPrevious = event.time
local xOffset = ( 0.2 * tDelta )
road.x = road.x - xOffset
road2.x = road2.x - xOffset
if (road.x + road.contentWidth) < 0 then
road:translate( 2247/4 * 2, 0)
end
if (road2.x + road2.contentWidth) < 0 then
road2:translate( 2247/4 * 2, 0)
end
Runtime:addEventListener( "enterFrame", move )
or see the sample code of jungle scene game.
Location: SampleApps/Sprites/JungleScene
Try this:
local bg1 = display.newImageRect( "bg_1.png" ,480 ,320)
bg1.x = display.contentWidth/2; bg1.y = display.contentHeight/2
local bg2 = display.newImageRect( "bg_2.png" ,480 ,320 )
bg2.x = bg1.x + bg1.width; bg2.y = display.contentHeight/2
local speed = 30
function move()
bg1.x = bg1.x-speed;
bg2.x = bg2.x-speed;
if(bg1.x + bg1.width/2 < 0)then bg1.x = bg1.width*3/2-speed
elseif(bg2.x + bg2.width/2 < 0)then bg2.x = bg2.width*3/2-speed end
end
Runtime:addEventListener( "enterFrame", move )
Keep coding............ :)
Thanks #krs and #Malar, combining your answers I figured out how to do this:
local function updateFrame(event)
local speed = fish.x - lfx
lfx = fish.x
camera.x = -fish.x + screenWidth / 2
bg1.x = bg1.x - speed
bg2.x = bg2.x - speed
if bg1.x + bg1.width < 0 then
bg1.x = bg1.x + screenWidth * 2
end
if bg2.x + bg2.width < 0 then
bg2.x = bg2.x + screenWidth * 2
end
if bg1.x - bg1.width > 0 then
bg1.x = bg1.x - screenWidth * 2
end
if bg2.x - bg2.width > 0 then
bg2.x = bg2.x - screenWidth * 2
end
end
Runtime:addEventListener( "enterFrame", updateFrame );
Starting positions:
bg1.x = screenLeft
bg2.x = bg1.x + bg1.width
And the last most important change:
I put bg1, bg2 and camera into a group and other objects into camera group:
local camera = require("camera")
group = display.newGroup()
group:insert(bg1)
group:insert(bg2)
camera:insert(fish)
camera:insert(ground)
group:insert(camera)
So we have ground and fish, which can move forever, but the backgrounds are only moving from -screenWidth to screenWidth.
All these things combined works like a charm!