Drag the Wall

From OxeyeWiki

Revision as of 11:38, 7 February 2010 by Jeb (Talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Contents

Description

In Drag the Wall your objective is to pull the white wall piece with your mouse so that it touches all of the small white boxes. In the small room there are four defense towers that charge up a blast that will kill you, so you need to find safe spots not to get caught.

dragthewall.jpg

This example was rewritten for DaisyMoon 1.1.0. Download all files here: dragthewall.zip

Disclaimer: DaisyMoon is pretty bad at doing 3D since it's mainly a 2D engine. Doing 3D stuff is dodgy, to say the least.

Assets

Files

main.lua

math.randomseed( os.time() )

dofile("vectorMath.lua")

-- copy from global namespace
local vectorMath, video, math = _vectorMath, video, math
local d45 = math.cos(math.pi * .25)

local circleSprite, blockSprite, tankNode, light, myPhysics

local cameraPosition = { x = 0, y = 0, z = -9.5 }
local cameraTarget = { x = 0, y = 0, z = 0 }

local testMaterial = {
	texture = "daisyMoon/speckle.jpg",
	lighting = true,
	zbuffer = true,
	zwrite = true,
	clockwiseCull = false,
	materialType = 0,
}
local transparentMaterial = {
	texture = "daisyMoon/speckle.jpg",
	lighting = true,
	zbuffer = true,
	zwrite = false,
	clockwiseCull = false,
	materialType = 11,
}

local chain = {}
local obstacles = {}
local items = {}
local transparent = {}
local gameData = {
	selectedLink = nil,
	lastSelectedLink = nil,
	gameOver = 0,
}

local function positionOnZedPlane(x, y)

	local sx, sy, sz, ex, ey, ez = video.getCameraRay(x, y)

	-- calculate collision with Z plane
	local x = sx - ((ex - sx) * sz) / (ez - sz)
	local y = sy - ((ey - sy) * sz) / (ez - sz)

	return x, y
end


local function createBevel(width, height, depth)

	-- front
	local fx1, fx2, fy1, fy2, fz = -width + depth, width - depth, -height + depth, height - depth, -depth

	local bevel = {

				-- front							-- left								-- right					-- bottom					-- top
		x = {	fx1, fx1, fx2, fx2,					-width, -width, fx1, fx1,			fx2, fx2, width, width,		-width, fx1, fx2, width,	fx1, -width, width, fx2 },
		y = {	fy1, fy2, fy2, fy1,					-height, height, fy2, fy1,			fy1, fy2, height, -height,	-height, fy1, fy1, -height,	fy2, height, height, fy2 },
		z = {	fz, fz, fz, fz,						0, 0, fz, fz,						fz, fz, 0, 0,				0, fz, fz, 0,				fz, 0, 0, fz },

		nx = {	0, 0, 0, 0,							-d45, -d45, -d45, -d45,				d45, d45, d45, d45,			0, 0, 0, 0,					0, 0, 0, 0 },
		ny = {	0, 0, 0, 0,							0, 0, 0, 0,							0, 0, 0, 0,					d45, d45, d45, d45,			-d45, -d45, -d45, -d45 },
		nz = {	-1, -1, -1, -1,						-d45, -d45, -d45, -d45,				-d45, -d45, -d45, -d45,		-d45, -d45, -d45, -d45,		-d45, -d45, -d45, -d45 },

		u = {0, 0, 1, 1,							0, 0, 1, 1,							0, 0, 1, 1,					0, 0, 1, 1,					0, 0, 1, 1 },
		v = {0, 1, 1, 0,							0, 1, 1, 0, 						0, 1, 1, 0,					0, 1, 1, 0,					0, 1, 1, 0 },

		i = { 0, 1, 2, 0, 2, 3,						4, 5, 6, 4, 6, 7,					8, 9, 10, 8, 10, 11,		12, 13, 14, 12, 14, 15,		16, 17, 18, 16, 18, 19 },
		tris = 10,
		verts = 20,

		physX = { -width, -width, width, width },
		physY = { height, -height, -height, height },

	}

	return bevel
end

local function transformBevel(bevel, formX, formY, formCX1, formCY1, formCX2, formCY2)

	local copy = {
		-- copy references to tables that aren't modified
		z = bevel.z,
		nz = bevel.nz,
		u = bevel.u,
		v = bevel.v,
		i = bevel.i,
		tris = bevel.tris,
		verts = bevel.verts
	}

	-- transform x and y
	copy.x, copy.y = {}, {}
	copy.nx, copy.ny = {}, {}
	for i=1,bevel.verts do
		copy.x[i], copy.y[i] = vectorMath.xFormMultiply(formX, formY, formCX1, formCY1, formCX2, formCY2, bevel.x[i], bevel.y[i])
		copy.nx[i], copy.ny[i] = vectorMath.xFormMultiply(0, 0, -formCX1, -formCY1, -formCX2, -formCY2, -bevel.nx[i], bevel.ny[i])
	end
	--copy.nx, copy.ny = bevel.nx, bevel.ny

	return copy
end

local function createTransparent(x, y, w, h, d)

	local o = {}
	o.bevel = createBevel(w * .5, h * .5, d)
	o.body = myPhysics:createEntity({}, x, y)
	myPhysics:addBoxShape(o.body, { x = 0, y = 0, width = w, height = h, density = 10, isSensor = true })
	myPhysics:activateEntity(o.body)

	table.insert(transparent, o)

	return o

end

local chargeCounter = 1
local function createObstacle(x, y, w, h, d, isCharger)

	local o = {}
	o.bevel = createBevel(w * .5, h * .5, d)
	o.body = myPhysics:createEntity({}, x, y)
	myPhysics:addBoxShape(o.body, { x = 0, y = 0, width = w, height = h, density = 10 })

	if isCharger then
		o.isCharger = true
		o.chargeTimer = -10 + math.random() * -15
		if chargeCounter == 1 then
			o.chargeTimer = 0
		end

		o.chargeOverlay = createTransparent(x, y, w + 3.5, h + 3.5, d + .1)

		o.chargeSound = "warning" .. chargeCounter .. ".wav"
		chargeCounter = chargeCounter + 1
		if chargeCounter > 4 then
			chargeCounter = 1
		end
	end

	table.insert(obstacles, o)

	return o

end

local function createItem(x, y)

	local i = {}
	i.bevel = createBevel(.25, .25, .1)
	i.body = myPhysics:createEntity({linearDamping = 1, angularDamping = 1}, x, y)
	myPhysics:addBoxShape(i.body, { x = 0, y = 0, width = .5, height = .5, density = .5, userData = "item_" .. #items })
	myPhysics:setEntityAngle(i.body, math.random() * 2.0 * math.pi)

	myPhysics:activateEntity(i.body)

	table.insert(items, i)

	return i

end


local function gameInit()

	--video.setScreenSize(1280, 960)

	circleSprite = video.createSpriteState("Circle", "itt.dat")
	blockSprite = video.createSpriteState("Square", "itt.dat")

	--tankNode = video.createSceneNode("tank.obj", "tex.tga", 0, 0, 0, 0, 0, 0, 1, 1, 1)
	video.setCameraPosition(cameraPosition.x, cameraPosition.y, cameraPosition.z)
	video.setCameraViewPosition(cameraTarget.x, cameraTarget.y, cameraTarget.z)
	--video.setCameraUpVector(0, 0, -1)
	light = video.createLightSceneNode(0, 0, -3, 6)

	tankNode = video.createSceneNode("120poly.obj", "speckle.jpg", 4, 1, 37.5, 0, 0, 0, .5, .5, .5)

	myPhysics = Physics(-1000, -1000, 1000, 1000, 0, 0)

	local bodyDef = { linearDamping = 20, angularDamping = 20, fixedRotation = false, isBullet = false }
	local startY = -5.5

	chain.links = {}
	for i=1,1 do
		chain.links[i] = {}
		chain.links[i].bevel = createBevel(.25, 1.5, .1)
		chain.links[i].body = myPhysics:createEntity(bodyDef, 0, startY + (i-1) * -1)
		myPhysics:addBoxShape(chain.links[i].body, { x = 0, y = 0, width = .5, height = 3, density = 5, friction = .1, restitution = 1 })
		myPhysics:activateEntity(chain.links[i].body)

		if i > 1 then
			-- link with previous piece

			-- 1: Create a body between the pieces
			local shapeA = myPhysics:createEntity(bodyDef, 0, startY + (i-2) * -1 - .5)
			myPhysics:addBoxShape(shapeA, {x = 0, y = 0, width = .2, height = .6, density = 1, userData = "player"})
			myPhysics:activateEntity(shapeA)

			-- 2: Attach the shape to the previous piece
			myPhysics:createRevoluteJoint(shapeA, chain.links[i-1].body, 0, startY + (i-2) * -1 - .5 + .3, {enableLimit = true, lowerAngle = math.pi * -.1, upperAngle = math.pi * .1})

			myPhysics:createRevoluteJoint(shapeA, chain.links[i].body, 0, startY + (i-2) * -1 - .5 - .3, {enableLimit = true, lowerAngle = math.pi * -.1, upperAngle = math.pi * .1})
		end
	end


	local o = createObstacle(-4, 2.5, 2, 3, .3)
	myPhysics:setEntityAngle(o.body, math.pi * .3)
	createObstacle(-4, -2, 2, 3, .29)
	createObstacle(4, -5, 2, 6, .29)

	createObstacle(4, 2.5, 2, 3, .3)
	createObstacle(0, 0, 3, 2, .3)

	createObstacle(4, 2.5, 1.5, 1.5, .4, true)


	createObstacle(4, -3, 1.5, 1.5, .4, true)
	o = createObstacle(-4, 2.5, 1.5, 1.5, .4, true)
	myPhysics:setEntityAngle(o.body, math.pi * .3)
	createObstacle(-4, -2, 1.5, 1.5, .4, true)

	createObstacle(-8.5, 0, 2, 11, .3)
	createObstacle(0, 6.5, 19, 2, .3)
	createObstacle(8.5, 0, 2, 11, .3)
	createObstacle(-4.5, -18, 8.5, 25, .3)
	createObstacle(4.5, -18, 8.5, 25, .3)

	--createTransparent(4, -3, 5.5, 5.5, .45)
	--createTransparent(-4, 2.5, 5.5, 5.5, .45)
	--createTransparent(-4, -2, 5.5, 5.5, .45)
	--createTransparent(4, 2.5, 5.5, 5.5, .45)

	for i=1,30 do
		createItem(math.random() * 12 - 6, math.random() * 8 - 4)
	end

	--[[
	local grid = {
		{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
		{ 1, 0, 0, 0, 0, 0, 0, 1, 0, 1 },
		{ 1, 1, 1, 1, 0, 0, 0, 0, 0, 1 },
		{ 1, 0, 0, 0, 0, 0, 0, 1, 0, 1 },
		{ 1, 0, 0, 1, 1, 1, 0, 0, 0, 1 },
		{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
		{ 1, 1, 1, 1, 0, 0, 1, 1, 1, 1 },
		{ 0, 0, 0, 1, 0, 0, 1, 0, 0, 0 },
		{ 0, 0, 0, 1, 0, 0, 1, 0, 0, 0 },
		{ 0, 0, 0, 1, 0, 0, 1, 0, 0, 0 },
	}
	local gridSize = 2
	for y=1,#grid do
		for x=1,#grid[y] do
			if grid[y][x] > 0 then
				createObstacle(-(gridSize * 5.5) + x * gridSize, -2 + (gridSize * #grid) - y * gridSize, gridSize, gridSize, .2)
			end
		end
	end
	]]

end
hook.add("gameInit", gameInit)

local cameraTime = 0
local function gameUpdate(time)

	--local w,h = video.getScreenSize()

	if time > .06 then
		time = .06
	end

	cameraTime = cameraTime + time
	video.setSceneNodeRotation(tankNode, cameraTime * math.pi * .038, cameraTime * math.pi * .338, cameraTime * math.pi)
	--cameraPosition.x = math.cos(cameraTime) * 3
	--video.setCameraPosition(cameraPosition.x, cameraPosition.y, cameraPosition.z)
	--video.setSceneNodePosition(light, cameraPosition.x, cameraPosition.y, cameraPosition.z)

	myPhysics:update(time, 10)

	if daisy.isMouseButtonPressed(0) and gameData.gameOver == 0 then

		local mx, my = daisy.getMousePosition()
		local wx, wy = positionOnZedPlane(mx, my)

		if gameData.selectedLink then

			-- pull link based on delta distance
			local cx, cy, x1, y1, x2, y2 = myPhysics:getEntityXForm(gameData.selectedLink.body)
			--gameData.startWX, gameData.startWY = wx, wy

			local localX, localY = vectorMath.xFormMultiply(cx, cy, x1, y1, x2, y2, gameData.startX, gameData.startY)
			local dx, dy = (wx - localX), (wy - localY)

			local diff = math.sqrt(dx * dx + dy * dy)
			if diff > 0 then
				dx = dx / diff
				dy = dy / diff

				myPhysics:applyEntityForce(gameData.selectedLink.body, localX, localY, dx * 700, dy * 700)
			end


		else

			for i=1,#chain.links do
				local cx, cy, x1, y1, x2, y2 = myPhysics:getEntityXForm(chain.links[i].body)
				local xCoords, yCoords = {}, {}

				for v=1,#chain.links[i].bevel.physX do
					xCoords[v], yCoords[v] = vectorMath.xFormMultiply(cx, cy, x1, y1, x2, y2, chain.links[i].bevel.physX[v], chain.links[i].bevel.physY[v])
				end

				chain.links[i].isPointInside = true

				for v=1,4 do

					local u = v + 1
					if u > 4 then
						u = 1
					end

					-- vector from v to u
					local dx, dy = xCoords[u] - xCoords[v], yCoords[u] - yCoords[v]
					-- vector from v to position
					local tx, ty = wx - xCoords[v], wy - yCoords[v]

					if vectorMath.cross22(dx, dy, tx, ty) < 0 then
						chain.links[i].isPointInside = false
					end
				end
				if chain.links[i].isPointInside then
					gameData.selectedLink = chain.links[i]
					gameData.startX, gameData.startY = vectorMath.xFormInvert(cx, cy, x1, y1, x2, y2, wx, wy)
					gameData.startWX, gameData.startWY = wx, wy
				end
			end
		end
	else
		if gameData.selectedLink then
			gameData.selectedLink.isPointInside = false
		end
		gameData.selectedLink = nil
	end


	do
		if gameData.selectedLink then
			--gameData.lastSelectedLink = gameData.selectedLink
		end
		if not gameData.lastSelectedLink then
			gameData.lastSelectedLink = chain.links[1]
		end
		local cx, cy, x1, y1, x2, y2 = myPhysics:getEntityXForm(gameData.lastSelectedLink.body)
		video.setSceneNodePosition(light, cx, cy, -2)


		local px, py = cx, cy

		for index, item in ipairs(items) do

			cx, cy, x1, y1, x2, y2 = myPhysics:getEntityXForm(item.body)

			-- attempt to avoid the player!
			local dx, dy = px - cx, py - cy
			local diff = math.sqrt(dx * dx + dy * dy)

			item.runAwayTimer = item.runAwayTimer or 0
			item.runAwayTimer = item.runAwayTimer + time
			if item.runAwayTimer > 3 then
				item.runLeft = not item.runLeft
				item.runAwayTimer = math.random()
			end

			if diff < 3 then
				dx = dx / diff
				dy = dy / diff

				-- rotate 90 degrees
				local temp = dx
				dx = -dy
				dy = temp

				local run = 2
				if item.runLeft then
					run = -2
				end

				myPhysics:applyEntityForce(item.body, cx, cy, dx * run, dy * run)
			else
				dx = 2 * dx / diff
				dy = 2 * dy / diff
				myPhysics:applyEntityForce(item.body, cx, cy, -dx, -dy)
			end

		end

		local impacts = myPhysics:getEntityCollisions(gameData.lastSelectedLink.body)
		if impacts then
			for i=1,#impacts do
				if impacts[i].impulse > 1 then
					--print("impact " .. impacts[i].impulse)

					local found = false

					-- locate if it was an item we hit
					for index, item in ipairs(items) do

						if item.body == impacts[i].id then
							--print("killed item")
							audio.playSound("death.wav")
							myPhysics:deleteEntity(item.body)
							table.remove(items, index)

							found = true
							break
						end

					end
					if not found then
						if impacts[i].impulse > 30 then
							audio.playSound("collide" .. math.random(1,3) .. ".wav")
						end
					end
				end
			end
		end

		local playerSensors = myPhysics:getEntitySensorPoints(gameData.lastSelectedLink.body)
		if playerSensors then

			for s=1,#playerSensors do
				for index, obstacle in ipairs(transparent) do
					if obstacle.body == playerSensors[s].id and obstacle.activeTimer and obstacle.activeTimer > 0 then
						--print("hit by sensor")
						gameData.gameOver = 2
					end
				end
			end
		end

	end

	if gameData.gameOver == 0 then
		for index, obstacle in ipairs(obstacles) do

			if obstacle.isCharger then
				obstacle.chargeTimer = obstacle.chargeTimer + time * 2

				local prevFlash = obstacle.doFlash
				obstacle.doFlash = obstacle.chargeTimer > 0 and math.sin(obstacle.chargeTimer * obstacle.chargeTimer) > .8

				if not prevFlash and obstacle.doFlash then
					audio.playSound(obstacle.chargeSound, .2 + obstacle.chargeTimer / 20, 0, .5 + obstacle.chargeTimer / 15)
				end

				if obstacle.chargeTimer > 15 then
					obstacle.chargeTimer = -math.random() * 20

					obstacle.chargeOverlay.activeTimer = 1

					audio.playSound("explosion1.wav", .6)
				end

			end

		end
	end

	for index, obstacle in ipairs(transparent) do

		obstacle.rotationTimer = obstacle.rotationTimer or 0
		obstacle.rotationTimer = obstacle.rotationTimer + time * 10

		myPhysics:setEntityAngle(obstacle.body, obstacle.rotationTimer)

		if obstacle.activeTimer and obstacle.activeTimer > 0 then
			obstacle.activeTimer = obstacle.activeTimer - time
		end

	end

	if #items == 0 and gameData.gameOver == 0 then
		gameData.gameOver = 1
	end

end
hook.add("frameUpdate", gameUpdate)


local bgGrid = {

	x = { -.1, -.1, 0, 0, .1, .1, 0, 0 },
	y = { -1, 1, 1, -1, 1, -1, -1, 1 },
	z = { .1, .1, 0, 0, .1, .1, 0, 0 },

	nx = { -d45, -d45, -d45, -d45, d45, d45, d45, d45 },
	ny = { 0, 0, 0, 0, 0, 0, 0, 0 },
	nz = { -d45, -d45, -d45, -d45, -d45, -d45, -d45, -d45 },

	u = { 0, 0, 1, 1, 0, 0, 1, 1 },
	v = { 0, 1, 1, 0, 0, 1, 1, 0 },

	i = { 0, 1, 2, 0, 2, 3,  4, 5, 6, 4, 6, 7 },

	tris = 4,
	verts = 8,

}

do
	-- generate bg grid

	local v = 1
	local i = 1

	local zOff = 0

	for yCount=1,5 do

		local y = 6 - yCount * 2

		for xCount=1,7 do

			local x = -8 + xCount * 2

			-- create back and front
			bgGrid.x[v + 0] = x - .1
			bgGrid.x[v + 1] = x - .1
			bgGrid.x[v + 2] = x
			bgGrid.x[v + 3] = x

			bgGrid.x[v + 4] = x + .1
			bgGrid.x[v + 5] = x + .1
			bgGrid.x[v + 6] = x
			bgGrid.x[v + 7] = x

			bgGrid.y[v + 0] = y - 1
			bgGrid.y[v + 1] = y + 1
			bgGrid.y[v + 2] = y + 1
			bgGrid.y[v + 3] = y - 1

			bgGrid.y[v + 4] = y + 1
			bgGrid.y[v + 5] = y - 1
			bgGrid.y[v + 6] = y - 1
			bgGrid.y[v + 7] = y + 1

			bgGrid.z[v + 0] = .1 + zOff
			bgGrid.z[v + 1] = .1 + zOff
			bgGrid.z[v + 2] = 0 + zOff
			bgGrid.z[v + 3] = 0 + zOff

			bgGrid.z[v + 4] = .1 + zOff
			bgGrid.z[v + 5] = .1 + zOff
			bgGrid.z[v + 6] = 0 + zOff
			bgGrid.z[v + 7] = 0 + zOff

			bgGrid.nx[v + 0] = -d45
			bgGrid.nx[v + 1] = -d45
			bgGrid.nx[v + 2] = -d45
			bgGrid.nx[v + 3] = -d45

			bgGrid.nx[v + 4] = d45
			bgGrid.nx[v + 5] = d45
			bgGrid.nx[v + 6] = d45
			bgGrid.nx[v + 7] = d45

			bgGrid.ny[v + 0] = 0
			bgGrid.ny[v + 1] = 0
			bgGrid.ny[v + 2] = 0
			bgGrid.ny[v + 3] = 0

			bgGrid.ny[v + 4] = 0
			bgGrid.ny[v + 5] = 0
			bgGrid.ny[v + 6] = 0
			bgGrid.ny[v + 7] = 0

			bgGrid.nz[v + 0] = -d45
			bgGrid.nz[v + 1] = -d45
			bgGrid.nz[v + 2] = -d45
			bgGrid.nz[v + 3] = -d45

			bgGrid.nz[v + 4] = -d45
			bgGrid.nz[v + 5] = -d45
			bgGrid.nz[v + 6] = -d45
			bgGrid.nz[v + 7] = -d45

			bgGrid.u[v + 0] = 0
			bgGrid.u[v + 1] = 0
			bgGrid.u[v + 2] = 1
			bgGrid.u[v + 3] = 1

			bgGrid.u[v + 4] = 0
			bgGrid.u[v + 5] = 0
			bgGrid.u[v + 6] = 1
			bgGrid.u[v + 7] = 1

			bgGrid.v[v + 0] = 0
			bgGrid.v[v + 1] = 1
			bgGrid.v[v + 2] = 1
			bgGrid.v[v + 3] = 0

			bgGrid.v[v + 4] = 0
			bgGrid.v[v + 5] = 1
			bgGrid.v[v + 6] = 1
			bgGrid.v[v + 7] = 0

			bgGrid.i[i + 0] = v + 0 - 1
			bgGrid.i[i + 1] = v + 1 - 1
			bgGrid.i[i + 2] = v + 2 - 1
			bgGrid.i[i + 3] = v + 0 - 1
			bgGrid.i[i + 4] = v + 2 - 1
			bgGrid.i[i + 5] = v + 3 - 1

			bgGrid.i[i + 6] = v + 4 - 1
			bgGrid.i[i + 7] = v + 5 - 1
			bgGrid.i[i + 8] = v + 6 - 1
			bgGrid.i[i + 9] = v + 4 - 1
			bgGrid.i[i + 10] = v + 6 - 1
			bgGrid.i[i + 11] = v + 7 - 1

			v = v + 8
			i = i + 12

			-- create top and bottom
			bgGrid.x[v + 0] = x - 1
			bgGrid.x[v + 1] = x + 1
			bgGrid.x[v + 2] = x + 1
			bgGrid.x[v + 3] = x - 1

			bgGrid.x[v + 4] = x - 1
			bgGrid.x[v + 5] = x + 1
			bgGrid.x[v + 6] = x + 1
			bgGrid.x[v + 7] = x - 1

			bgGrid.y[v + 0] = y + .1
			bgGrid.y[v + 1] = y + .1
			bgGrid.y[v + 2] = y
			bgGrid.y[v + 3] = y

			bgGrid.y[v + 4] = y
			bgGrid.y[v + 5] = y
			bgGrid.y[v + 6] = y - .1
			bgGrid.y[v + 7] = y - .1

			bgGrid.z[v + 0] = .1 + zOff
			bgGrid.z[v + 1] = .1 + zOff
			bgGrid.z[v + 2] = 0 + zOff
			bgGrid.z[v + 3] = 0 + zOff

			bgGrid.z[v + 4] = 0 + zOff
			bgGrid.z[v + 5] = 0 + zOff
			bgGrid.z[v + 6] = .1 + zOff
			bgGrid.z[v + 7] = .1 + zOff

			bgGrid.nx[v + 0] = 0
			bgGrid.nx[v + 1] = 0
			bgGrid.nx[v + 2] = 0
			bgGrid.nx[v + 3] = 0

			bgGrid.nx[v + 4] = 0
			bgGrid.nx[v + 5] = 0
			bgGrid.nx[v + 6] = 0
			bgGrid.nx[v + 7] = 0

			bgGrid.ny[v + 0] = d45
			bgGrid.ny[v + 1] = d45
			bgGrid.ny[v + 2] = d45
			bgGrid.ny[v + 3] = d45

			bgGrid.ny[v + 4] = -d45
			bgGrid.ny[v + 5] = -d45
			bgGrid.ny[v + 6] = -d45
			bgGrid.ny[v + 7] = -d45

			bgGrid.nz[v + 0] = -d45
			bgGrid.nz[v + 1] = -d45
			bgGrid.nz[v + 2] = -d45
			bgGrid.nz[v + 3] = -d45

			bgGrid.nz[v + 4] = -d45
			bgGrid.nz[v + 5] = -d45
			bgGrid.nz[v + 6] = -d45
			bgGrid.nz[v + 7] = -d45

			bgGrid.u[v + 0] = 0
			bgGrid.u[v + 1] = 0
			bgGrid.u[v + 2] = 1
			bgGrid.u[v + 3] = 1

			bgGrid.u[v + 4] = 0
			bgGrid.u[v + 5] = 0
			bgGrid.u[v + 6] = 1
			bgGrid.u[v + 7] = 1

			bgGrid.v[v + 0] = 0
			bgGrid.v[v + 1] = 1
			bgGrid.v[v + 2] = 1
			bgGrid.v[v + 3] = 0

			bgGrid.v[v + 4] = 0
			bgGrid.v[v + 5] = 1
			bgGrid.v[v + 6] = 1
			bgGrid.v[v + 7] = 0

			bgGrid.i[i + 0] = v + 0 - 1
			bgGrid.i[i + 1] = v + 1 - 1
			bgGrid.i[i + 2] = v + 2 - 1
			bgGrid.i[i + 3] = v + 0 - 1
			bgGrid.i[i + 4] = v + 2 - 1
			bgGrid.i[i + 5] = v + 3 - 1

			bgGrid.i[i + 6] = v + 4 - 1
			bgGrid.i[i + 7] = v + 5 - 1
			bgGrid.i[i + 8] = v + 6 - 1
			bgGrid.i[i + 9] = v + 4 - 1
			bgGrid.i[i + 10] = v + 6 - 1
			bgGrid.i[i + 11] = v + 7 - 1

			v = v + 8
			i = i + 12
		end
	end

	bgGrid.verts = v - 1
	bgGrid.tris = bgGrid.verts / 2

end

local function render()

	local w,h = video.getScreenSize()


	video.setMaterial(testMaterial)

	do
		local a, r, g, b = {}, {}, {}, {}
		local intensity = 200 + math.floor(55 * math.random())
		for v=1,bgGrid.verts do
			a[v] = 255
			r[v] = intensity
			g[v] = 128
			b[v] = 128
		end

		video.renderTriangleListWithNormals(
			bgGrid.verts, bgGrid.tris, bgGrid.i,
			bgGrid.x, bgGrid.y, bgGrid.z,
			bgGrid.nx, bgGrid.ny, bgGrid.nz,
			bgGrid.u, bgGrid.v,
			a, r, g, b
		)
	end

	for i=1,#chain.links do
		local cx, cy, x1, y1, x2, y2 = myPhysics:getEntityXForm(chain.links[i].body)
		local bevel = transformBevel(chain.links[i].bevel, cx, cy, x1, y1, x2, y2)

		local a, r, g, b = {}, {}, {}, {}
		local intensity = 200 + math.floor(55 * math.random())
		for v=1,bevel.verts do
			a[v] = 255
			--if chain.links[i].isPointInside then
			--	r[v] = 0
			--	g[v] = intensity
			--	b[v] = 0
			--else
				r[v] = intensity
				g[v] = intensity
				b[v] = intensity
			--end
		end

		video.renderTriangleListWithNormals(
			bevel.verts, bevel.tris, bevel.i,
			bevel.x, bevel.y, bevel.z,
			bevel.nx, bevel.ny, bevel.nz,
			bevel.u, bevel.v,
			a, r, g, b
		)


	end

	for index, obstacle in ipairs(obstacles) do
		local cx, cy, x1, y1, x2, y2 = myPhysics:getEntityXForm(obstacle.body)
		local bevel = transformBevel(obstacle.bevel, cx, cy, x1, y1, x2, y2)

		local a, r, g, b = {}, {}, {}, {}
		local intensity = 200 + math.floor(55 * math.random())
		for v=1,bevel.verts do
			if obstacle.doFlash then
				a[v] = 255
				r[v] = 255
				g[v] = 255
				b[v] = 255
			else
				a[v] = 255
				r[v] = intensity
				g[v] = 0
				b[v] = 0
			end
		end

		video.renderTriangleListWithNormals(
			bevel.verts, bevel.tris, bevel.i,
			bevel.x, bevel.y, bevel.z,
			bevel.nx, bevel.ny, bevel.nz,
			bevel.u, bevel.v,
			a, r, g, b
		)

	end

	for index, item in ipairs(items) do
		local cx, cy, x1, y1, x2, y2 = myPhysics:getEntityXForm(item.body)
		local bevel = transformBevel(item.bevel, cx, cy, x1, y1, x2, y2)

		local a, r, g, b = {}, {}, {}, {}
		local intensity = 200 + math.floor(55 * math.random())
		for v=1,bevel.verts do
			a[v] = 255
			r[v] = intensity
			g[v] = intensity
			b[v] = intensity
		end

		video.renderTriangleListWithNormals(
			bevel.verts, bevel.tris, bevel.i,
			bevel.x, bevel.y, bevel.z,
			bevel.nx, bevel.ny, bevel.nz,
			bevel.u, bevel.v,
			a, r, g, b
		)

	end

	video.render3dScene()
	--video.renderSpriteState3d(circleSprite, 0, 0, -0.01, 0, 1.0 / 96.0, false, 255, 255, 0, 0)

	video.setMaterial(transparentMaterial)
	for index, obstacle in ipairs(transparent) do

		if obstacle.activeTimer and obstacle.activeTimer > 0 then

			local cx, cy, x1, y1, x2, y2 = myPhysics:getEntityXForm(obstacle.body)
			local bevel = transformBevel(obstacle.bevel, cx, cy, x1, y1, x2, y2)

			local a, r, g, b = {}, {}, {}, {}
			local intensity = 200 + math.floor(55 * math.random())
			for v=1,bevel.verts do
				a[v] = 128
				r[v] = intensity
				g[v] = intensity
				b[v] = intensity
			end

			video.renderTriangleListWithNormals(
				bevel.verts, bevel.tris, bevel.i,
				bevel.x, bevel.y, bevel.z,
				bevel.nx, bevel.ny, bevel.nz,
				bevel.u, bevel.v,
				a, r, g, b
			)
		end

	end

	if gameData.gameOver > 0 then
		if gameData.gameOver == 1 then
			video.renderText("You won", 400, 300 - 20, 1)
		elseif gameData.gameOver == 2 then
			video.renderText("You lost", 400, 300, 1)
		end
		video.renderText("Press Ctrl+R to Play Again", 400, 300 + 20, 1)
		video.renderText("Press Q to Quit", 400, 300 + 30, 1)

		video.renderText("A Game by Jens Bergensten for Ludum Dare 14", 400, 550, 1)
		video.renderText("http://www.oxeyegames.com", 400, 565, 1)
	end


end
hook.add("frameRender", render)


local function keyPressed(key)

	if key == 81 then -- Q

		daisy.exitGame()
	end

end
hook.add("keyPress", keyPressed)

vectorMath.lua

This is a vector math lua file that we use in many projects.


-- GLOBALS

_vectorMath = {}

-- LOCALS
local vectorMath = _vectorMath

vectorMath.cross2 = function(x, y, z)
	return y * z, -x * z
end

vectorMath.cross22 = function(x1, y1, x2, y2)
	return x1 * y2 - y1 * x2
end

vectorMath.dot2 = function(x1, y1, x2, y2)
	return x1 * x2 + y1 * y2
end

vectorMath.normalize2 = function(x, y)
	local length = math.sqrt(vectorMath.dot2(x, y, x, y))
	return x / length, y / length
end

vectorMath.xFormMultiply = function(formX, formY, formCX1, formCY1, formCX2, formCY2, x, y)

	local newX = formCX1 * x + formCX2 * y
	local newY = formCY1 * x + formCY2 * y

	return newX + formX, newY + formY
end

vectorMath.xFormInvert = function(formX, formY, formCX1, formCY1, formCX2, formCY2, x, y)

	x = x - formX
	y = y - formY

	local d = formCX1 * formCY2 - formCY1 * formCX2

	local oldX = (formCY2 * x - formCX2 * y) / d
	local oldY = (formCX1 * y - formCY1 * x) / d

	return oldX, oldY
end

vectorMath.pointToLineSquareDistance = function(x, y, x1, y1, x2, y2)

	-- get vector from start to test point and to end
	local px, py = x - x1, y - y1
	local vx, vy = x2 - x1, y2 - y1

	-- also get vectors from the other end, to see if the test point is between
	local px2, py2 = x - x2, y - y2
	local vx2, vy2 = x1 - x2, y1 - y2

	-- the dots between these vectors must have equal signs
	local dot1 = vectorMath.dot2(px, py, vx, vy)
	local dot2 = vectorMath.dot2(px2, py2, vx2, vy2)
	if (dot1 < 0 and dot2 > 0) or (dot1 > 0 and dot2 < 0) then
		-- return the distance to the closest end point
		local dist1 = px * px + py * py
		local dist2 = px2 * px2 + py2 * py2
		if dist1 < dist2 then
			return dist1
		end
		return dist2
	end


	-- project the test vector on the line vector, and calculate rejection
	local scale = dot1 / (vx*vx + vy*vy)
	local nx, ny = vx * scale - px, vy * scale - py

	return nx * nx + ny * ny


end
Personal tools
Namespaces
Variants
Actions
Navigation
Toolbox