In the camera example, how to avoid camera moving beyond a certain world coordinate (ie, having bounds) when it's scaled?
There is no limitation for the camera move so far. I don't plan to add some so far, but do you request it?
I think it's up to the application logic, not the engine.
I do the following algorithm:
I think about to publish that like ebiten extension library. But don't know when it becomes ready for open source :)
It looks like this:
func (v *View) FixGeomToBounds(imageRect, screeRect Rect) {
v.fixGeom.Reset()
geom := v.GeoM()
x0, y0 := geom.Apply(0, 0)
_, y1 := geom.Apply(0, imageRect.Heigth)
transformedImgHieght := y1 - y0
z := math.Sqrt(imageRect.Heigth * imageRect.Heigth /
transformedImgHieght / transformedImgHieght)
if z > 1 {
v.fixGeom.Scale(z, z)
geom.Concat(v.fixGeom)
x0, y0 = geom.Apply(0, 0)
}
if x0 > 0 {
v.fixGeom.Translate(-x0, 0)
}
if y0 > 0 {
v.fixGeom.Translate(0, -y0)
}
x1, y1 := geom.Apply(imageRect.Width, imageRect.Heigth)
if x1 < screeRect.Width {
v.fixGeom.Translate(screeRect.Width-x1, 0)
}
if y1 < screeRect.Heigth {
v.fixGeom.Translate(0, screeRect.Heigth-y1)
}
}
There is no limitation for the camera move so far. I don't plan to add some so far, but do you request it?
It would be great to have it in the camera example.
I think it's up to the application logic, not the engine.
You're absolutely right, @kulti. Not every game needs it. Your algorithm looks like what I'm trying to implement, but I could not fully understand it. Do you mind sharing the rest of the code?
@joaowiciuk, my algorithm hardcoded for my environment. I try to explain with pieces of code. For all transformation I used the following article.
Assumptions:
Algorithm:
type View struct {
viewGeom ebiten.GeoM // current state
touchGeom ebiten.GeoM // transformations during current touch hanlding
fixGeom ebiten.GeoM // need to bound view to edges
touches []image.Point // previous touches
}
func (v *View) GeoM() ebiten.GeoM {
geom := v.viewGeom
geom.Concat(v.touchGeom)
geom.Concat(v.fixGeom)
return geom
}
func (v *View) Commit() {
v.viewGeom = v.GeoM()
v.touchGeom.Reset()
v.fixGeom.Reset()
v.touches = nil
}
3.2 If one touch - it's a scrolling:
func (v *View) handleScrollTouch(touch image.Point) {
v.touchGeom.Reset()
v.touchGeom.Translate(float64(touch.X-v.touches[0].X), float64(touch.Y-v.touches[0].Y))
}
3.3 If two touches - it's a zoom and a scrolling:
func (v *View) handleMultTouch(touches []image.Point) {
m1 := magnitudeSquare(v.touches[0], v.touches[1])
m2 := magnitudeSquare(touches[0], touches[1])
scale := math.Sqrt(m2 / m1)
v.touchGeom.Reset()
v.touchGeom.Translate(-float64(v.touches[0].X), -float64(v.touches[0].Y))
v.touchGeom.Scale(scale, scale)
v.touchGeom.Translate(float64(touches[0].X), float64(touches[0].Y))
}
func magnitudeSquare(p1, p2 image.Point) float64 {
dx := p2.X - p1.X
dy := p2.Y - p1.Y
return float64(dx*dx + dy*dy)
}
Hopes, it helps.
Hello everyone! Thanks for your answers
I've come with a solution to this problem that I think it's worth sharing here
First, I rewrote the Camera struct in the camera example to
type Camera struct {
View image.Rectangle
Limit image.Rectangle
Zoom int
}
Then created the function
func (c *Camera) Move(dx, dy float64) {
if dx == 0 && dy == 0 {
return
}
x0, y0 := c.ScreenToWorld(0, 0)
x1, y1 := c.ScreenToWorld(c.View.Dx(), c.View.Dy())
worldView := image.Rect(int(x0), int(y0), int(x1), int(y1))
displacement := image.Pt(int(dx), int(dy))
if worldView.Min.X < c.Limit.Min.X && dx < 0 {
displacement.X = 0
}
if worldView.Min.Y < c.Limit.Min.Y && dy < 0 {
displacement.Y = 0
}
if worldView.Max.X > c.Limit.Max.X && dx > 0 {
displacement.X = 0
}
if worldView.Max.Y > c.Limit.Max.Y && dy > 0 {
displacement.Y = 0
}
newCameraView := c.View.Add(displacement)
c.View = newCameraView
}
So I could just call it in the Update loop like this:
dMax := 8.0
var dx, dy float64
if ebiten.IsKeyPressed(ebiten.KeyA) {
dx = -dMax
}
if ebiten.IsKeyPressed(ebiten.KeyD) {
dx = dMax
}
if ebiten.IsKeyPressed(ebiten.KeyW) {
dy = -dMax
}
if ebiten.IsKeyPressed(ebiten.KeyS) {
dy = dMax
}
The rest of the code is just a matter of adaptation
Most helpful comment
@joaowiciuk, my algorithm hardcoded for my environment. I try to explain with pieces of code. For all transformation I used the following article.
Assumptions:
Algorithm:
3.1 If no touches - commits geom chates to current state:
3.2 If one touch - it's a scrolling:
3.3 If two touches - it's a zoom and a scrolling:
Hopes, it helps.