zoomer

package
v0.0.0-...-5b3fe6d Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 23, 2025 License: MIT Imports: 2 Imported by: 0

Documentation

Overview

This package defines a Zoomer interface that the ebipixel camera can use to update its position, and provides a few default implementations.

All provided implementations respect a few properties:

  • Resolution independent: range of motion for the tracking is not hardcoded, but proportional to the game's resolution.
  • Update-rate independent: as long as the total ticks per second remain the same, different Tick().UPS() values will still reproduce the same results. See ups-vs-tps if you need more context. Many implementations are actually also tick-rate independent.

These are nice properties for public implementations, but if you are writing your own, remember that most often these properties won't be relevant to you. You can ignore them and make your life easier if you are only getting started.

Warning: avoid bringing cameras to 0.1 and similarly low zoom levels. At those levels, zoomer bounciness and overshoot can make your game collapse very easily. It's better to be at x3.0 zoom by default most of the time than going to super low values that might be unstable and dangerous to work with. There are many sources of unstability, like different update/tick rate configurations, changing zooms mid-transition and so on. Always strive to operate either with generous safety margins or very safe zoomers without bounciness.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Constant

type Constant struct {
	// contains filtered or unexported fields
}

A very simple zoomer that modifies the zoom at a constant speed, which can be changed through Constant.SetSpeed().

By default, the change is not purely linear, though, it's multiplied by the current zoom level. This can be changed through Constant.SetZoomCompensated(false). The reason for this is that going from x1.0 to x2.0 zoom doesn't result in /2.0 the surface to draw, but /4.0. Therefore, to have a perceptually linear change in zoom, using a linear speed doesn't quite work, we also need to multiply the change by the current zoom level.

The implementation is update-rate independent.

func (*Constant) Reset

func (self *Constant) Reset()

func (*Constant) SetSpeed

func (self *Constant) SetSpeed(newSpeed float64, transition TicksDuration)

The default speed is 1.0, reasonable values range between [0.5, 3.0].

The method also requires a second parameter indicating the duration of the transition from the old speed to the new one, in ticks.

func (*Constant) SetZoomCompensated

func (self *Constant) SetZoomCompensated(compensated bool)

With zoom compensation, the zoom looks perceptually linear. Without zoom compensation, zooming in seems to progressively slow down, and zooming out seems to progressively speed up. This is explained in more detail on the documentation of Constant itself.

Defaults to true.

func (*Constant) Update

func (self *Constant) Update(currentZoom, targetZoom float64) float64

type Quadratic

type Quadratic struct {
	// contains filtered or unexported fields
}

After writing a few zoomers, I saw I liked quadratic in/out curves more than springs. This is some kind of v2 for SmoothLinear and RoughLinear, with less magic hardcoded numbers, less bouncing by default, but still smooth turns mid-transition.

The zoom can still bounce if the target is suddenly changed, but it's more stable in general. Like, it's purely quadratic in/out if we don't change targets mid-transition and there are enough updates per second for the simulation to be accurate.

The implementation is tick-rate independent.

func (*Quadratic) Reset

func (self *Quadratic) Reset()

Implements Zoomer.

func (*Quadratic) SetAcceleration

func (self *Quadratic) SetAcceleration(acceleration float64)

The default is 3.66. Reasonable values range between [0.3, 16.0].

func (*Quadratic) SetMaxSpeed

func (self *Quadratic) SetMaxSpeed(maxSpeed float64)

The default is 5.0.

func (*Quadratic) Update

func (self *Quadratic) Update(currentZoom, targetZoom float64) float64

Implements Zoomer.

type RoughLinear

type RoughLinear struct {
	// contains filtered or unexported fields
}

Somewhat similar to SmoothLinear, but without any bouncing and rougher turns mid-transition.

It also has a customizable speed factor.

The implementation is tick-rate independent.

func (*RoughLinear) Reset

func (self *RoughLinear) Reset()

Implements Zoomer.

func (*RoughLinear) SetSpeedFactor

func (self *RoughLinear) SetSpeedFactor(factor float64)

Speed factor must be strictly positive. Defaults to 1.0.

func (*RoughLinear) Update

func (self *RoughLinear) Update(currentZoom, targetZoom float64) float64

Implements Zoomer.

type SmoothLinear

type SmoothLinear struct {
	// contains filtered or unexported fields
}

An implementation of the Zoomer interface that uses linear interpolation for zoom speeds, but with some additional smoothing factors. Very handcrafted, can "spring" a bit (overshoot the target and rebound).

The implementation is tick-rate independent.

func (*SmoothLinear) Reset

func (self *SmoothLinear) Reset()

Implements Zoomer.

func (*SmoothLinear) Update

func (self *SmoothLinear) Update(currentZoom, targetZoom float64) float64

Implements Zoomer.

type Spring

type Spring struct {
	// contains filtered or unexported fields
}

Springy zoom. By default, it barely overshoots, but you can set it to be more or less bouncy if you want.

The implementation is tick-rate independent.

func (*Spring) Reset

func (self *Spring) Reset()

Implements Zoomer.

func (*Spring) SetMaxTargetDistance

func (self *Spring) SetMaxTargetDistance(maxDistance float64)

Can help tame maximum speeds if desired. Setting it to 0.0 disables the maximum target distance.

func (*Spring) SetParameters

func (self *Spring) SetParameters(damping, power float64)

Damping values must be in [0.0, 1.0] range. Power depends on damping, but must be strictly positive. Defaults are (0.85, 2.5).

func (*Spring) SetZoomCompensation

func (self *Spring) SetZoomCompensation(compensation float64)

See Constant.SetZoomCompensated() for context. Compensating zooms with the spring zoomer will lead to overshoot on zoom ins and undershoot on zoom outs for normal to high power values.

Parameters will also have to be adjusted, as the results get very different. I recommend starting at (0.87, 1.6) if you set zoom compensation to 1. I also like (0.8, 1.5) at 0.6.

The compensation is also a bit more sophisticated than on Constant, so if you really expect specific results, just dive directly into the code.

Defaults to 0.

func (*Spring) Update

func (self *Spring) Update(currentZoom, targetZoom float64) float64

Implements Zoomer.

type TicksDuration

type TicksDuration = internal.TicksDuration

Alias for mipix.TicksDuration.

type Zoomer

type Zoomer interface {
	Reset()
	Update(currentZoom, targetZoom float64) (change float64)
}

The interface for ebipixel camera zooming.

Given current and target zoom levels, the Update() method returns the zoom change for a single update. Reset() is used to indicate an instantaneous zoom level reset instead.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL