func New(filename string, sprite sprite.Sprite, a ...interface{}) *ParticleSystem { ps := new(ParticleSystem) if len(a) == 1 { if fps, ok := a[0].(float64); ok { if fps != 0.0 { ps.updateSpeed = 1.0 / fps } } } ps.h = hge.New() ps.rand = rand.New(int(timer.Time())) ps.rand.Seed() ptr := resource.LoadBytes(filename) if ptr == nil { ps.h.Log("Particle file (%s) seems to be empty.", filename) return nil } // skip the first four bytes i := uintptr(4) // Ok, First we reflect the ParticleSystemInfo struct s := reflect.ValueOf(&ps.Info).Elem() // Then we loop through each element, skipping sprite for obvious reasons for j := 1; j < s.NumField(); j++ { // Then we get the field of the struct f := s.Field(j) // Here we examine the type switch f.Type().String() { case "float64": // Then we set the structure's field to the value at the current // byte(s) // We cast the value pointed to by the ptr[i] with unsafe.Pointer f.SetFloat(float64(*(*float32)(cast(&ptr[i])))) // Next we skip ahead based on the size of the data read i += unsafe.Sizeof(float32(0.0)) case "int": f.SetInt(int64(*(*int32)(cast(&ptr[i])))) i += unsafe.Sizeof(int32(0)) case "bool": f.SetBool(*(*bool)(cast(&ptr[i]))) i += unsafe.Sizeof(bool(false)) i += 3 // padding case "color.ColorRGB": for k := 0; k < 4; k++ { f.Field(k).SetFloat(float64(*(*float32)(cast(&ptr[i])))) i += unsafe.Sizeof(float32(0.0)) } } } ps.Info.Sprite = sprite ps.age = -2.0 ps.particles = make([]particle, hgeMAX_PARTICLES+1) return ps }
// Loads a resource, puts the loaded data into a byte array, and frees the data. func (h *HGE) ResourceLoadBytes(filename string) []byte { return resource.LoadBytes(filename) }