## Wrap images around game window

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
zorg
Party member
Posts: 3055
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

### Re: Wrap images around game window

corners.png (1.71 KiB) Viewed 3019 times
The green ones are basically missing.
Me and my stuff True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.

Lucyy
Prole
Posts: 42
Joined: Thu Oct 15, 2015 6:57 am
Contact:

### Re: Wrap images around game window

If you paste them together that should be the full shape again ;o

Edit: my bad, just realised the corners would be missing.

OnACoffeeBreak
Prole
Posts: 28
Joined: Tue Apr 11, 2017 11:19 am

### Re: Wrap images around game window

I figured it out (.love) of the test project is attached. I don't know if this very efficient. I haven't wrapped my mind around doing collision detection with this setup.

Visualizing this helped me think it through. Here's what I came up with on a piece of paper. The thick rectangle is the window. "ww" is window width. "wh" is the window height. Primary image is the player image that is normally updated. Wrap images are only drawn if the primary is needs to be wrapped around the window borders.

There are four "corner" cases: A, B, C and D. General case consists of 8 wrap images in addition to the primary image. Note that because I rotate my player around the center, the origin of the player image is in the center of the image.
wrap.png (11.04 KiB) Viewed 2997 times
The code that deals with wrapping (also see .love file attached) is this:

Code: Select all

function love.update(dt)
local wh = love.graphics.getHeight()
local ww = love.graphics.getWidth()
local wrap_coord_offsets =
{
{x = 0,   y = -wh}, -- top
{x = ww,  y = -wh}, -- top right
{x = ww,  y = 0},   -- right
{x = ww,  y = wh},  -- bottom right
{x = 0,   y = wh},  -- bottom
{x = -ww, y = wh},  -- bottom left
{x = -ww, y = 0},   -- left
{x = -ww, y = -wh}  -- top left
}

-- Clear wrapped image coordinates. They are about to be recalculated.
for i, wco in ipairs(p.wrap_coords) do
p.wrap_coords[i] = nil
end

-- Calculate coordinates of all 8 images used for wrapping around borders
-- Only add to p.wrap_coords if the image is visible
for i, wco in ipairs(wrap_coord_offsets) do
local x = p.x + wco.x
local y = p.y + wco.y
if isVisible(x, y, p.ox, p.oy) then
-- Whichever one of these has its coords inside the window becomes the
-- primary image. Don't add it to the secondary wrap images
if x >= 0 and x < ww and y >= 0 and y < wh then
p.x = x
p.y = y
else
table.insert(p.wrap_coords, {x = x, y = y})
end
end
end
end

function love.draw()
-- Rotate player image around its center.
-- This moves the origin to the center of the image
love.graphics.draw(p.image, p.x, p.y, p.a, 1, 1, p.ox, p.oy)

-- Draw any boundary wrapping images
for i, wc in ipairs(p.wrap_coords) do
love.graphics.draw(p.image, wc.x, wc.y, p.a, 1, 1, p.ox, p.oy)
end
end
In border_cross_test.love, WASD is used to move the image around. Q and E are used to rotate the image. One thing I noticed is that the image blinks when the center is crossing the y=0 horizontal line and x=ww vertical line. This doesn't happen at y=wh horiz and x=0 vert.

If anyone takes a look at the code and has suggestions for how to improve it or general comments on the code, I am all ears. In other words, I will appreciate any feedback.

Thanks!
Attachments
border_cross_test.love

airstruck
Party member
Posts: 650
Joined: Thu Jun 04, 2015 7:11 pm
Location: Not being time thief.

### Re: Wrap images around game window

You might want to avoid creating a temporary table every frame and only draw as many times as needed. Something like this should be simpler:

Code: Select all

local function drawPlayerAt (x, y)
love.graphics.draw(p.image, x, y, p.a, 1, 1, p.ox, p.oy)
end

local function getEdge (pos, rad, max)
if pos - rad < 0 then return pos + max end
if pos + rad > max then return pos - max end
end

function love.draw ()
local x = getEdge(p.x, p.w, WINDOW_WIDTH)
local y = getEdge(p.y, p.h, WINDOW_HEIGHT)

drawPlayerAt(p.x, p.y)                  -- draw at real position
if x then drawPlayerAt(x, p.y) end      -- draw horizontal wrap
if y then drawPlayerAt(p.x, y) end      -- draw vertical wrap
if x and y then drawPlayerAt(x, y) end  -- draw corner wrap
end

MasterLee
Party member
Posts: 141
Joined: Tue Mar 07, 2017 4:03 pm
Contact:

### Re: Wrap images around game window

Make sure that the sprite position (upper left edge of sprite) is always in the interval [0,width) and [0, height). This is easily done by calculating x=x%width and y=y%height. Next make two helping variables for wrapped Position wx=x-width and wy=y-height. Now u can draw all four sprites

Code: Select all

local function drawPlayerAt (x, y)
love.graphics.draw(p.image, x, y, p.a, 1, 1, p.ox, p.oy)
end

local function getEdge (pos, rad, max)
pos = pos - max
if -pos < rad then return pos end
end

function love.draw ()
-- you need this in update function anyway so better do it in update
p.x=p.x%WINDOW_WIDTH
p.y=p.y%WINDOW_HEIGHT
local x = getEdge(p.x, p.w, WINDOW_WIDTH)
local y = getEdge(p.y, p.h, WINDOW_HEIGHT)

drawPlayerAt(p.x, p.y)                  -- draw at real position
if x then drawPlayerAt(x, p.y) end      -- draw horizontal wrap
if y then drawPlayerAt(p.x, y) end      -- draw vertical wrap
if x and y then drawPlayerAt(x, y) end  -- draw corner wrap
end

airstruck
Party member
Posts: 650
Joined: Thu Jun 04, 2015 7:11 pm
Location: Not being time thief.

### Re: Wrap images around game window

Why the change to getEdge? It won't wrap from left to right or top to bottom like that, only from right to left and bottom to top.

OnACoffeeBreak
Prole
Posts: 28
Joined: Tue Apr 11, 2017 11:19 am

### Re: Wrap images around game window

Thanks for the feedback! Indeed, much simpler that way.
airstruck wrote:
Thu Apr 13, 2017 6:44 am
You might want to avoid creating a temporary table every frame and only draw as many times as needed.
I left that there in case the window is resized. Thanks!

MasterLee
Party member
Posts: 141
Joined: Tue Mar 07, 2017 4:03 pm
Contact:

### Re: Wrap images around game window

airstruck wrote:
Thu Apr 13, 2017 3:47 pm
Why the change to getEdge? It won't wrap from left to right or top to bottom like that, only from right to left and bottom to top.
Because when assured that postion is in range [0,size) then there will be no wrap from left to right let me show:
assume size is 100
and the sprite size is 20
now when an sprite is drawn at x=90
we calculate
x=x%size → x=90%100=90
wx=x-size → wx=90-100=-10
so we draw the sprite at 90 and also on -10. When this left edge of it the right edge will be on 110 and 10.
Now for example you sprite moved to -10
we calculate
x=x%size → x=-10%100=90
wx=x-size → wx=90-100=-10
so we draw on exactly the same position

That is because when ever calculating x=x%size in your code you assure that x in the range [0,size)
Now assume your sprite moved to 190
without check your sprite would be drawn only once in the visible area
However when your sprite is moved to 290 it will will not be drawn at all
but when you calculate x=x%size it will be back to 90 again

airstruck
Party member
Posts: 650
Joined: Thu Jun 04, 2015 7:11 pm
Location: Not being time thief.

### Re: Wrap images around game window

What if the center of the sprite is at x=10 in your example, though? You won't see it on the right side of the screen, but you should. Test it out.

MasterLee
Party member
Posts: 141
Joined: Tue Mar 07, 2017 4:03 pm
Contact:

### Re: Wrap images around game window

Thats why i told the sprite position should be defined by upper left conner
But alternative you can change the range to [half sprite size,size of screen + half sprite size)
Changing the formula to will do
x=((x-spritezise/2)%size)+spritesize/2

### Who is online

Users browsing this forum: No registered users and 48 guests