Added a base (mainly initialization).
This commit is contained in:
parent
9d2b259ba1
commit
a56ceae2e3
42
README.md
42
README.md
@ -1,7 +1,47 @@
|
|||||||
# TINS 2020
|
# TINS 2020
|
||||||
|
|
||||||
## Additional Rules
|
## Additional Rules
|
||||||
TBD
|
|
||||||
|
### Genre requirement
|
||||||
|
**** There will be 1 genre rule
|
||||||
|
|
||||||
|
**genre rule #130**
|
||||||
|
|
||||||
|
Theme: Flowers - There should be different flowers in the game, the more the better!
|
||||||
|
Comments: This rule just reminds me of my favourite platformer, Super Mario World 2: Yoshi's island - it was FULL of flowers: flower enemies, flower collectables, flowers in the background, flowers that grow to form new platforms, shy guys using flowers as camouflage in the flower beds...
|
||||||
|
|
||||||
|
### Artistic requirements
|
||||||
|
**** There will be 1 artistical rule
|
||||||
|
|
||||||
|
**artistical rule #60**
|
||||||
|
make fun of old-fashioned things.
|
||||||
|
Comments:E.g. have a mode in which the game plays in black and white, featuring an old granny in the corner saying "I didn't pay my colour television license for this", or occasionally "I was in a war" Some more inspirations [here](https://www.youtube.com/watch?v=67OPI3cXAaE) and [here](https://twitter.com/Bill_Gross/status/920406104911233024)
|
||||||
|
|
||||||
|
### Technical requirement
|
||||||
|
**** There will be 2 technical rules
|
||||||
|
|
||||||
|
**technical rule #10**
|
||||||
|
|
||||||
|
Your game must include procedural content. Bonus points if procedural generation is used to create the gameplay environment.
|
||||||
|
|
||||||
|
**technical rule #68**
|
||||||
|
|
||||||
|
some kind of special text scroller
|
||||||
|
|
||||||
|
Comments: I'll leave you with some inspirational links
|
||||||
|
|
||||||
|
- [Wikipedia on procedural generation](https://en.wikipedia.org/wiki/Procedural_generation)
|
||||||
|
- [Extra Credits video on procedural content](https://www.youtube.com/watch?v=TgbuWfGeG2o)
|
||||||
|
- [A star wars text scroller](http://blogs.sitepointstatic.com/examples/tech/css3-starwars/index.html)
|
||||||
|
- [An old fasioned text scroller from the demo scene](https://www.youtube.com/watch?v=3rcXPBJhFf4)
|
||||||
|
|
||||||
|
### Bonus rule
|
||||||
|
**** There will be 1 bonus rule
|
||||||
|
|
||||||
|
**bonus rule #9**
|
||||||
|
|
||||||
|
Act of monkey - you may replace a single rule by a rule that has the opposite effect
|
||||||
|
Comments: Lots of wiggle room here. For example, you could revert the last technical rule to have a non-text scroller, non-scrolling text, or simply, no text scroller.
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
Prerequisites:
|
Prerequisites:
|
||||||
|
70
cmd/example/example.go
Normal file
70
cmd/example/example.go
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
// author: Jacky Boen
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/veandco/go-sdl2/img"
|
||||||
|
"github.com/veandco/go-sdl2/sdl"
|
||||||
|
)
|
||||||
|
|
||||||
|
var winTitle string = "Go-SDL2 Texture"
|
||||||
|
var winWidth, winHeight int32 = 800, 600
|
||||||
|
var imageName string = "../../assets/test.png"
|
||||||
|
|
||||||
|
func run() int {
|
||||||
|
var window *sdl.Window
|
||||||
|
var renderer *sdl.Renderer
|
||||||
|
var texture *sdl.Texture
|
||||||
|
var src, dst sdl.Rect
|
||||||
|
var err error
|
||||||
|
|
||||||
|
window, err = sdl.CreateWindow(winTitle, sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED,
|
||||||
|
winWidth, winHeight, sdl.WINDOW_SHOWN)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "Failed to create window: %s\n", err)
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
defer window.Destroy()
|
||||||
|
|
||||||
|
renderer, err = sdl.CreateRenderer(window, -1, sdl.RENDERER_ACCELERATED)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "Failed to create renderer: %s\n", err)
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
defer renderer.Destroy()
|
||||||
|
|
||||||
|
image, err := img.Load(imageName)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "Failed to load PNG: %s\n", err)
|
||||||
|
return 3
|
||||||
|
}
|
||||||
|
defer image.Free()
|
||||||
|
|
||||||
|
texture, err = renderer.CreateTextureFromSurface(image)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "Failed to create texture: %s\n", err)
|
||||||
|
return 4
|
||||||
|
}
|
||||||
|
defer texture.Destroy()
|
||||||
|
|
||||||
|
src = sdl.Rect{0, 0, 512, 512}
|
||||||
|
dst = sdl.Rect{100, 50, 512, 512}
|
||||||
|
|
||||||
|
renderer.Clear()
|
||||||
|
renderer.SetDrawColor(255, 0, 0, 255)
|
||||||
|
renderer.FillRect(&sdl.Rect{0, 0, int32(winWidth), int32(winHeight)})
|
||||||
|
renderer.Copy(texture, &src, &dst)
|
||||||
|
renderer.Present()
|
||||||
|
|
||||||
|
sdl.PollEvent()
|
||||||
|
sdl.Delay(2000)
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
os.Exit(run())
|
||||||
|
}
|
15
cmd/tins2020/terrainrenderer.go
Normal file
15
cmd/tins2020/terrainrenderer.go
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "opslag.de/schobers/tins2020"
|
||||||
|
|
||||||
|
type terrainRenderer struct {
|
||||||
|
terrain *tins2020.Map
|
||||||
|
}
|
||||||
|
|
||||||
|
func newTerrainRenderer(terrain *tins2020.Map) *terrainRenderer {
|
||||||
|
return &terrainRenderer{terrain}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *terrainRenderer) Render(ctx *tins2020.Context) {
|
||||||
|
|
||||||
|
}
|
@ -3,7 +3,10 @@ package main
|
|||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
|
rice "github.com/GeertJohan/go.rice"
|
||||||
"github.com/veandco/go-sdl2/sdl"
|
"github.com/veandco/go-sdl2/sdl"
|
||||||
|
"github.com/veandco/go-sdl2/ttf"
|
||||||
|
"opslag.de/schobers/tins2020"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@ -19,33 +22,66 @@ func run() error {
|
|||||||
}
|
}
|
||||||
defer sdl.Quit()
|
defer sdl.Quit()
|
||||||
|
|
||||||
window, err := sdl.CreateWindow("TINS 2020", sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED,
|
if err := ttf.Init(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer ttf.Quit()
|
||||||
|
|
||||||
|
ctx, err := tins2020.NewContext(rice.MustFindBox("res"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer ctx.Destroy()
|
||||||
|
|
||||||
|
if ctx.Settings.Window.Location == nil {
|
||||||
|
ctx.Settings.Window.Location = &tins2020.Point{
|
||||||
|
X: sdl.WINDOWPOS_UNDEFINED,
|
||||||
|
Y: sdl.WINDOWPOS_UNDEFINED,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window, err := sdl.CreateWindow("TINS 2020", ctx.Settings.Window.Location.X, ctx.Settings.Window.Location.Y,
|
||||||
800, 600, sdl.WINDOW_SHOWN)
|
800, 600, sdl.WINDOW_SHOWN)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer window.Destroy()
|
defer window.Destroy()
|
||||||
|
|
||||||
surface, err := window.GetSurface()
|
renderer, err := sdl.CreateRenderer(window, -1, sdl.RENDERER_ACCELERATED)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
surface.FillRect(nil, 0)
|
defer renderer.Destroy()
|
||||||
|
|
||||||
rect := sdl.Rect{0, 0, 200, 200}
|
ctx.Init(renderer)
|
||||||
surface.FillRect(&rect, 0xffff0000)
|
|
||||||
window.UpdateSurface()
|
err = ctx.Fonts.Load("default", "fonts/OpenSans-Regular.ttf", 12)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
running := true
|
running := true
|
||||||
for running {
|
for running {
|
||||||
for event := sdl.PollEvent(); event != nil; event = sdl.PollEvent() {
|
for event := sdl.PollEvent(); event != nil; event = sdl.PollEvent() {
|
||||||
switch event.(type) {
|
switch e := event.(type) {
|
||||||
case *sdl.QuitEvent:
|
case *sdl.QuitEvent:
|
||||||
println("Quit")
|
println("Quit")
|
||||||
running = false
|
running = false
|
||||||
break
|
break
|
||||||
|
case *sdl.WindowEvent:
|
||||||
|
switch e.Event {
|
||||||
|
case sdl.WINDOWEVENT_MOVED:
|
||||||
|
x, y := window.GetPosition()
|
||||||
|
ctx.Settings.Window.Location = &tins2020.Point{X: x, Y: y}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderer.SetDrawColor(0, 0, 0, 255)
|
||||||
|
renderer.Clear()
|
||||||
|
renderer.SetDrawColor(255, 0, 0, 255)
|
||||||
|
renderer.FillRect(&sdl.Rect{0, 0, 200, 200})
|
||||||
|
renderer.Present()
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
38
context.go
Normal file
38
context.go
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package tins2020
|
||||||
|
|
||||||
|
import (
|
||||||
|
rice "github.com/GeertJohan/go.rice"
|
||||||
|
"github.com/veandco/go-sdl2/sdl"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Context struct {
|
||||||
|
Fonts Fonts
|
||||||
|
Resources Resources
|
||||||
|
Textures Textures
|
||||||
|
Settings Settings
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewContext(res *rice.Box) (*Context, error) {
|
||||||
|
ctx := &Context{}
|
||||||
|
err := ctx.Settings.Init()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = ctx.Resources.Open(res)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ctx, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Context) Init(renderer *sdl.Renderer) {
|
||||||
|
c.Fonts.Init(c.Resources.Copy())
|
||||||
|
c.Textures.Init(renderer)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Context) Destroy() {
|
||||||
|
c.Fonts.Destroy()
|
||||||
|
c.Resources.Destroy()
|
||||||
|
c.Textures.Destroy()
|
||||||
|
c.Settings.Store()
|
||||||
|
}
|
41
fonts.go
Normal file
41
fonts.go
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
package tins2020
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/veandco/go-sdl2/ttf"
|
||||||
|
"opslag.de/schobers/fs/vfs"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Fonts struct {
|
||||||
|
dir vfs.CopyDir
|
||||||
|
fonts map[string]*ttf.Font
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Fonts) Init(dir vfs.CopyDir) {
|
||||||
|
f.dir = dir
|
||||||
|
f.fonts = map[string]*ttf.Font{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Fonts) Load(name, path string, size int) error {
|
||||||
|
fontPath, err := f.dir.Retrieve(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
font, err := ttf.OpenFont(fontPath, size)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if font, ok := f.fonts[name]; ok {
|
||||||
|
font.Close()
|
||||||
|
}
|
||||||
|
f.fonts[name] = font
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Fonts) Destroy() {
|
||||||
|
if f.fonts == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, f := range f.fonts {
|
||||||
|
f.Close()
|
||||||
|
}
|
||||||
|
}
|
61
game.go
Normal file
61
game.go
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
package tins2020
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/rand"
|
||||||
|
|
||||||
|
"opslag.de/schobers/geom/noise"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Game struct {
|
||||||
|
Terrain *Map
|
||||||
|
Flowers []Flower
|
||||||
|
Bees []Bee
|
||||||
|
}
|
||||||
|
|
||||||
|
type Map struct {
|
||||||
|
Temp *NoiseMap
|
||||||
|
Humid *NoiseMap
|
||||||
|
}
|
||||||
|
|
||||||
|
type NoiseMap struct {
|
||||||
|
noise *noise.Perlin
|
||||||
|
alpha, beta float64
|
||||||
|
harmonics int
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewNoiseMap(seed int64) *NoiseMap {
|
||||||
|
return &NoiseMap{
|
||||||
|
noise: noise.NewPerlin(seed),
|
||||||
|
alpha: 2,
|
||||||
|
beta: 2,
|
||||||
|
harmonics: 4,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *NoiseMap) Value(x, y int) float64 {
|
||||||
|
return m.noise.Noise2D(float64(x), float64(y), m.alpha, m.beta, m.harmonics)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGame() *Game {
|
||||||
|
terrain := &Map{
|
||||||
|
Temp: NewNoiseMap(rand.Int63()),
|
||||||
|
Humid: NewNoiseMap(rand.Int63()),
|
||||||
|
}
|
||||||
|
return &Game{
|
||||||
|
Terrain: terrain,
|
||||||
|
Flowers: []Flower{},
|
||||||
|
Bees: []Bee{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type PointF struct {
|
||||||
|
X, Y float32
|
||||||
|
}
|
||||||
|
|
||||||
|
type Flower struct {
|
||||||
|
Location PointF
|
||||||
|
}
|
||||||
|
|
||||||
|
type Bee struct {
|
||||||
|
Location PointF
|
||||||
|
}
|
50
io.go
Normal file
50
io.go
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
package tins2020
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
func DecodeJSON(path string, v interface{}) error {
|
||||||
|
f, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
err = json.NewDecoder(f).Decode(v)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func EncodeJSON(path string, v interface{}) error {
|
||||||
|
f, err := os.Create(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
return json.NewEncoder(f).Encode(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func UserDir() (string, error) {
|
||||||
|
config, err := os.UserConfigDir()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
dir := filepath.Join(config, "tins2020")
|
||||||
|
err = os.MkdirAll(dir, 0777)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return dir, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func UserFile(name string) (string, error) {
|
||||||
|
dir, err := UserDir()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return filepath.Join(dir, name), nil
|
||||||
|
}
|
6
point.go
Normal file
6
point.go
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package tins2020
|
||||||
|
|
||||||
|
type Point struct {
|
||||||
|
X int32
|
||||||
|
Y int32
|
||||||
|
}
|
39
resources.go
Normal file
39
resources.go
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
package tins2020
|
||||||
|
|
||||||
|
import (
|
||||||
|
rice "github.com/GeertJohan/go.rice"
|
||||||
|
"github.com/spf13/afero"
|
||||||
|
"opslag.de/schobers/fs/ricefs"
|
||||||
|
"opslag.de/schobers/fs/vfs"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Resources struct {
|
||||||
|
box *rice.Box
|
||||||
|
fs afero.Fs
|
||||||
|
copy vfs.CopyDir
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Resources) Destroy() {
|
||||||
|
r.copy.Destroy()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Resources) Fs() afero.Fs {
|
||||||
|
return r.fs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Resources) Open(box *rice.Box) error {
|
||||||
|
r.box = box
|
||||||
|
r.fs = vfs.NewOsFsFallback(r.box.Name(), ricefs.NewFs(box))
|
||||||
|
copy, err := vfs.NewCopyDir(r.fs)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
r.copy = copy
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Resources) Copy() vfs.CopyDir { return r.copy }
|
||||||
|
|
||||||
|
func (r *Resources) Retrieve(name string) (string, error) {
|
||||||
|
return r.copy.Retrieve(name)
|
||||||
|
}
|
34
settings.go
Normal file
34
settings.go
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package tins2020
|
||||||
|
|
||||||
|
import "os"
|
||||||
|
|
||||||
|
type Settings struct {
|
||||||
|
Window WindowSettings
|
||||||
|
}
|
||||||
|
|
||||||
|
func SettingsPath() (string, error) {
|
||||||
|
return UserFile("settings.json")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Settings) Init() error {
|
||||||
|
path, err := SettingsPath()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return DecodeJSON(path, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Settings) Store() error {
|
||||||
|
path, err := SettingsPath()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return EncodeJSON(path, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
type WindowSettings struct {
|
||||||
|
Location *Point
|
||||||
|
}
|
39
textures.go
Normal file
39
textures.go
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
package tins2020
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/veandco/go-sdl2/img"
|
||||||
|
"github.com/veandco/go-sdl2/sdl"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Textures struct {
|
||||||
|
renderer *sdl.Renderer
|
||||||
|
textures map[string]*sdl.Texture
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Textures) Init(renderer *sdl.Renderer) {
|
||||||
|
t.renderer = renderer
|
||||||
|
t.textures = map[string]*sdl.Texture{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Textures) Load(name, path string, size int) error {
|
||||||
|
surface, err := img.Load(name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer surface.Free()
|
||||||
|
texture, err := t.renderer.CreateTextureFromSurface(surface)
|
||||||
|
if t.textures == nil {
|
||||||
|
t.textures = map[string]*sdl.Texture{}
|
||||||
|
}
|
||||||
|
t.textures[name] = texture
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Textures) Destroy() {
|
||||||
|
if t.textures == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, t := range t.textures {
|
||||||
|
t.Destroy()
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user