Generating isometric grid for tileset in Corona SDK - lua

I imported an isometric map made in tiled to Corona SDK and am now trying to overlay a grid layer. I've done a lot of reading into isometric grids but it seems they all reference tilesets where the height is half the width. (ex. 128x64px ). I am using a tileset that requires the grid to be 256x149px and I think I have to edit the grid generation function to accommodate the change. Any help would be greatly appreciated!
Screenshot of the issue (Using original Vectors):
Original Vectors: https://image.ibb.co/emXpQR/Screen_Shot_2017_12_18_at_1_35_19_PM.png
Edited Vectors (the ones commented out in code): https://image.ibb.co/ikxOkR/Screen_Shot_2017_12_18_at_1_35_54_PM.png
Grid Generation Code:
function drawGrid()
for row = 0, 16 do
local gridRow = {}
for col = 0, 9 do
-- draw a diamond shaped tile
local vertices = { 0,-16, -64,16, 0,48, 64,16 }
-- MY EDITED VERTICES { 0,-37.25, -128,37.25, 0,111.75, 128,37.25 }
local tile = display.newPolygon(group, 0, 0, vertices )
-- outline the tile and make it transparent
tile.strokeWidth = 1
tile:setStrokeColor( 0, 1, 1 )
tile.alpha = .4
local tileWidth = 256
local tileHeight = 149
-- set the tile's x and y coordinates
local x = col * tileHeight
local y = row * tileHeight
tile.x = (x - y)
tile.y = ((tileHeight/2) + ((x + y)/2))
-- make a tile walkable
gridRow[col] = 0
end
-- add gridRow table to the map table
j_map[row] = gridRow
end
end
As you can see in the screenshots the tiles kind of veer off the side of the map. If anyone knows how to fix it or needs more info on the information let me know!

Try code:
for row = 0, 16 do
local gridRow = {}
for col = 0, 9 do
-- draw a diamond shaped tile
--local vertices = { 0,-16, -64,16, 0,48, 64,16 }
-- MY EDITED VERTICES
local vertices = { 0,-37.25, -128,37.25, 0,111.75, 128,37.25 }
local tile = display.newPolygon( group, 0, 0, vertices )
-- outline the tile and make it transparent
tile.strokeWidth = 1
tile:setStrokeColor( 0, 1, 1 )
tile.alpha = .4
local tileWidth = 256
local tileHeight = 149
tile.x = -(row - col) * tileWidth * 0.5
tile.y = (row + col) * tileHeight * 0.5
-- make a tile walkable
gridRow[col] = 0
end
-- add gridRow table to the map table
--j_map[row] = gridRow
end
I get formula for xand y position of tile from Isometric Tiles Math. Good luck:)

Related

YOLO object detection opencv drawing a lot of rectangles

I have collected images of S9 phones, added labels with labellmg and trained for a few hours in google colab. I had minimal loss so I thought it is enough. I only selected the rectangles where the phone is displayed and nothing else. What I dont understand is, it draws a lot of rectangles on the phone. I only want 1 or 2 rectangles drawn on the phone itself. Did I do something wrong?
def detect_img(self, img):
blob = cv2.dnn.blobFromImage(img, 0.00392 ,(416,416), (0,0,0), True, crop=False)
input_img = self.net.setInput(blob)
output = self.net.forward(self.output)
height, width, channel = img.shape
boxes = []
trusts = []
class_ids = []
for out in output:
for detect in out:
total_scores = detect[5:]
class_id = np.argmax(total_scores)
trust_factor = total_scores[class_id]
if trust_factor > 0.5:
x_center = int(detect[0] * width)
y_center = int(detect[1] * height)
w = int(detect[2] * width)
h = int(detect[3] * height)
x = int(x_center - w / 2)
y = int(x_center - h / 2)
boxes.append([x,y,w,h])
trusts.append(float(trust_factor))
class_ids.append(class_id)
cv2.rectangle(img, (x_center,y_center), (x + w, y + h), (0,255,0), 2)
When I set the trust_factor to 0.8, a lot of the rectangles are gone but there are still rectangles outside the phone, while I only selected the phone itself in labellmg and not the background.
You can use function "non maximum suppression" that it removes rectangles which have less score. I put a code for NMS
def NMS(boxes, overlapThresh = 0.4):
# Return an empty list, if no boxes given
if len(boxes) == 0:
return []
x1 = boxes[:, 0] # x coordinate of the top-left corner
y1 = boxes[:, 1] # y coordinate of the top-left corner
x2 = boxes[:, 2] # x coordinate of the bottom-right corner
y2 = boxes[:, 3] # y coordinate of the bottom-right corner
# Compute the area of the bounding boxes and sort the bounding
# Boxes by the bottom-right y-coordinate of the bounding box
areas = (x2 - x1 + 1) * (y2 - y1 + 1) # We add 1, because the pixel at the start as well as at the end counts
# The indices of all boxes at start. We will redundant indices one by one.
indices = np.arange(len(x1))
for i,box in enumerate(boxes):
# Create temporary indices
temp_indices = indices[indices!=i]
# Find out the coordinates of the intersection box
xx1 = np.maximum(box[0], boxes[temp_indices,0])
yy1 = np.maximum(box[1], boxes[temp_indices,1])
xx2 = np.minimum(box[2], boxes[temp_indices,2])
yy2 = np.minimum(box[3], boxes[temp_indices,3])
# Find out the width and the height of the intersection box
w = np.maximum(0, xx2 - xx1 + 1)
h = np.maximum(0, yy2 - yy1 + 1)
# compute the ratio of overlap
overlap = (w * h) / areas[temp_indices]
# if the actual boungding box has an overlap bigger than treshold with any other box, remove it's index
if np.any(overlap) > treshold:
indices = indices[indices != i]
#return only the boxes at the remaining indices
return boxes[indices].astype(int)

How to "rotate" an ellipse?

Using this:
local W, H = 100, 50
function love.draw()
love.graphics.translate(love.graphics.getWidth()/2,love.graphics.getHeight()/2)
for i = 1, 360 do
local I = math.rad(i)
local x,y = math.cos(I)*W, math.sin(I)*H
love.graphics.line(0, 0, x, y)
end
end
I can connect a line with the center of an ellipse (with length W and height H) and the edge. How do you 'rotate' the ellipse around it's center, with a parameter R? I know you can sort of do it with love.graphics.ellipse and love.graphics.rotate but is there any way I can get the coordinates of the points on a rotated ellipse?
This is a Trigonometry problem, here is how the basic 2D rotation work. Imagine a point located at (x,y). If you want to rotate that point around the origin(in your case 0,0) by the angle θ, the coordinates of the new point would be located at (x1,y1) by using the following transformation
x1 = xcosθ − ysinθ
y1 = ycosθ + xsinθ
In your example, I added a new ellipse after rotations
function love.draw()
love.graphics.translate(love.graphics.getWidth()/2,love.graphics.getHeight()/2)
for i = 1, 360, 5 do
local I = math.rad(i)
local x,y = math.cos(I)*W, math.sin(I)*H
love.graphics.setColor(0xff, 0, 0) -- red
love.graphics.line(0, 0, x, y)
end
-- rotate by angle r = 90 degree
local r = math.rad(90)
for i = 1, 360, 5 do
local I = math.rad(i)
-- original coordinates
local x = math.cos(I) * W
local y = math.sin(I) * H
-- transform coordinates
local x1 = x * math.cos(r) - y * math.sin(r)
local y1 = y * math.cos(r) + x * math.sin(r)
love.graphics.setColor(0, 0, 0xff) -- blue
love.graphics.line(0, 0, x1, y1)
end
end

2D Hexagon grid

I recently made a simple lua class (this is using the love2D engine) that made a hexagon by plotting 6 vertices and tracing them with lines, one of the things I wanted to be able to expand to was a hexagon grid but I didn't know how
All of the websites I found didn't help and I couldn't understand why.
Here's the function where I plot the vertices based on it's radius and x and y position.
My hexagons are in a pointy-topped style.
function hexagon.new(x,y,radius)
local hexagon=setmetatable({},hexagon)
hexagon.Vertices={}
hexagon.x=x or 0
hexagon.radius = radius or 10
hexagon.y=y or 0
for i=0,6 do
local angle = 2 * math.pi / 6 * (i + .5) -- 1 is what is multipled to 90(2*math.pi) so 1*90=90(flat-topped), 0.5*90=45(pointy-topped)
local x = hexagon.x + hexagon.radius * math.cos(angle)
local y = hexagon.y + hexagon.radius * math.sin(angle)
hexagon.Vertices[i]= {x=x,y=y}
end
return hexagon
end
Hope i understood well.
Here is working example of how to create hex and then draw it to grid with as simplified functions as possible, using Love2d engine (v. 0.10.2).
important: made for hex which has all six points on circle, using radius.
this approach is not suitable for all hex shapes.
------------------------------
--lets create hex data with center at position 0,0
--using only simple functions
--table of 6 points
hex = {};
--radius for hex which has all 6 points lying on circle
hex.radius = 10;
--simple loop to generate hex
local i = 1
repeat
--full circle has 2 radians and hex has 6 points
--so 1/3 pi increase per point
local direction = math.pi/3 * (i+0.5)
--rotate hex by 90 degrees: direction = math.pi/3 * i
--generate empty table to insert point coordinations to
hex[i] = {};
--set x,y coordinates
hex[i].x = hex.radius*math.cos( direction )
hex[i].y = hex.radius*math.sin( direction )
i = i+1
until i > 6
------------------------------
------------------------------
function love.draw( dt )
--get distance between 2 hex tiles using trigonometry
local jxOffset = hex.radius*-math.tan( math.pi/1.5 ) --or math.sqrt(3) * hex.radius
--offset new lines by this value
local ixOffset = jxOffset/4
--use direction and distance to get "y" offset between lines
--we got distance in jxOffset, so we just apply direction
local iyOffset = jxOffset*math.sin( math.pi/3 )
--"i" = line, "j" = tile in line
local i = 1
repeat
local j = 1
repeat
love.graphics.push()
--offset drawable position (or draw hex tile at position):
love.graphics.translate( ixOffset+j*jxOffset, i*iyOffset )
--draw poly-line between all hex points - creating hex
love.graphics.line( hex[1].x,hex[1].y, hex[2].x,hex[2].y, hex[3].x,hex[3].y, hex[4].x,hex[4].y, hex[5].x,hex[5].y, hex[6].x,hex[6].y, hex[1].x,hex[1].y );
love.graphics.pop()
j = j+1
until j > 5
--invert for each new line
--keep lines from increasing x coordinates
ixOffset = -ixOffset
i = i+1
until i > 5
end
------------------------------
Excuse me if i made mistake somewhere, ran the code and worked properly on my side. If you discover anything off, comment and i will try to fix it.

Corona Vertices of a Hexagon

Ok, so I'm trying to create hexagons for my game. The first option I had is to have several images of hexagon, but I'm having problems with clickable area since these images are positioned side-by-side.
So i guess my only option is to create objects using polygons. Here is a code from corona sdk's website:
local halfW = display.contentWidth * 0.5
local halfH = display.contentHeight * 0.5
local vertices = { 0,-110, 27,-35, 105,-35, 43,16, 65,90, 0,45, -65,90, -43,15, -105,-35, -27,-35, }
local o = display.newPolygon( halfW, halfH, vertices )
o.fill = { type="image", filename="mountains.png" }
o.strokeWidth = 10
o:setStrokeColor( 1, 0, 0 )
That code is for creating a star. But I don't know how to create a hexagon using vertices.
Try this to create the vertices array:
local R = 45
local N = 6
local vertices = {}
local i = 0
for t = 0, 2*math.pi, 2*math.pi/N do
i=i+1; vertices[i]= R*math.cos(t)
i=i+1; vertices[i]= R*math.sin(t)
end
And this to draw the hexagon:
local halfW = display.contentWidth * 0.5
local halfH = display.contentHeight * 0.5
local hexagon = display.newPolygon( halfW, halfH, vertices )
hexagon.fill = { type="image", filename="mountains.png" }
hexagon.strokeWidth = 10
hexagon:setStrokeColor( 1, 0, 0 )
I chose R=45 to produce a polygon of the same size of your star.
You could always use a graphics.newMask() to apply a mask to each image hex that would make the outside area not touchable.

Drawing a circle with an evenly-distributed set-amount of points

I was wondering how you would go about this assuming you were working with a 2D coordinate frame in pixels. I created some examples of what I mean:
Red dot represents the origin point
Grey circle shows the radius but wouldn't actually be drawn
Green dots have a set amount and get evenly distributed along the
circle
With 3 dots:
http://prntscr.com/5vbj86
With 8 dots:
http://prntscr.com/5vbobd
Spektre answered my question but in C++, here it is in lua for anyone interested:
local x,y
local n = 10
local r = 100.0
local x0 = 250.0
local y0 = 250.0
local da = 2.0 * math.pi/n
local a = 0.0
for i = 0, n - 1 do
x = x0 + r * math.cos(a)
y = y0 + r * math.sin(a)
-- draw here using x,y
a = a + da
end
on circle very easy
for evenly distributed points the angle is increasing with the same step
so for N points the step is da=2.0*M_PI/N;
The code in C++ is like this:
int i,n=10;
double x,y,a,da;
double r=100.0,x0=250.0,y0=250.0; // circle definition
da=2.0*M_PI/double(n);
for (a=0.0,i=0;i<n;i++,a+=da)
{
x=x0+r*cos(a);
y=y0+r*sin(a);
// here draw or do something with (x,y) point
}

Resources