zoukankan      html  css  js  c++  java
  • Love2D游戏引擎制作贪吃蛇游戏

    代码地址如下:
    http://www.demodashi.com/demo/15051.html

    Love2D游戏引擎制作贪吃蛇游戏

    内附有linux下的makefile,windows下的生成方法请查看:

    for windows

    预览游戏

    love2d游戏引擎重要函数

    详情:

    love2d wiki

    • love.load:当游戏开始时被调用且仅调用一次

    • love.draw:回调函数,每帧更新一次游戏画面

    • love.update:回调函数,每帧更新一次游戏状态

    • love.keypressed:回调函数,当有按键被按下时触发

    • love.filesystem.load:加载一个lua脚本文件但不执行

    !其他的函数在用到时再做解释

    版本区别以及初始化资源

    !首先要注意的是,本次使用的游戏引擎时love 0.9版本,与最新的love 11.x版本稍有区别。在0.9版本中颜色使用0~255来表示,而在11.x版本中是0~1来表示。

    因为需要制作的游戏非常小,所以我们将所用到的资源在第一时间将其初始化并加载到内存中,以便使用。使用到的资源主要有:

    • 字体

    • 颜色

    • 声音

    • 窗口大小与块大小

    • 标题

    • 边框

    所用到的函数:

    • love.window.setMode:设置窗口大小,以及样式

    • love.window.setTitle:设置标题

    • love.graphics.newFont:加载字体文件,大小自定义,返回Font类型

    • love.audio.newSource:加载音效文件

    代码如下:

    function love.load ()
    	-- 块大小,窗口宽高,标题
    	cellSize = 20
    	width = 20 * 40
    	height = 20 * 25
    	title = 'SNAKE !'
    
    	-- 设置窗口大小和标题
    	love.window.setMode (width, height)
    	love.window.setTitle (title)
    
    	-- 加载不同大小字体
    	fonts = {
    		pixies100 = love.graphics.newFont ('Fonts/Pixies.TTF', 100),
    		pixies30 = love.graphics.newFont ('Fonts/Pixies.TTF', 30),
    		pixies10 = love.graphics.newFont ('Fonts/Pixies.TTF', 10)
    	}
    
    	-- 加载音效资源
    	sounds = {
    		showMenu = love.audio.newSource ('Sounds/showMenu.wav', 'stream'),
    		switchOption = love.audio.newSource ('Sounds/switchOption.wav', 'stream'),
    		eatFood = love.audio.newSource ('Sounds/eatFood.wav', 'stream'),
    		collided = love.audio.newSource ('Sounds/collided.wav', 'stream'),
    		gameOver = love.audio.newSource ('Sounds/gameOver.wav', 'stream')
    	}
    
    	-- 边框数据
    	border = {
    		1, 1,
    		width-1, 1,
    		width-1, height-1,
    		1, height-1,
    		1, 1
    	}
    
    	-- 颜色数据
    	colors = {
    		darkGray = { 0.3, 0.3, 0.3, 1 },
    		beiga = { 0.98, 0.91, 0.76, 1 },
    		white = { 1, 1, 1, 1 },
    		paleTurquoise = { 0.7, 1, 1, 1 },
    	}
    
    	SwitchScence ('Menu')
    end
    
    

    场景与其切换

    !首先我们需要实现一个简单的场景切换函数,因为一个游戏总是有多个场景

    1. 先将love2d引擎的主要回调函数赋值nil以免之后出现错误
    2. 加载新场景的lua脚本
    3. 执行新场景的lua脚本

    代码如下:

    function SwitchScence (scence)
    	-- 将重要的函数赋予空值,以免冲突
    	love.update = nil
    	love.draw = nil
    	love.keypressed = nil
    
    	-- 将需要的场景加载进来,并执行load函数
    	love.filesystem.load ('Scences/'..scence..'.lua') ()
    	love.load ()
    end
    
    -- 切换到初始化场景
    SwitchScence ('Init')
    

    绘制开始界面

    在这里我们需要认识一些绘图函数:

    • love.graphics.setFont:设置当期字体

    • love.graphics.setColor:设置当前颜色

    • love.graphics.rectangle:绘制矩形

    • love.graphics.line:绘制直线

    • love.graphics.print:在窗口上输出

    !绘制比较简单,其他详情都在代码里有详细注释,要注意的是我绘制选项的方法。options的有效长度并不是#options,而是options.count记录的选项数量

    代码如下:

    -- 游戏标题,以及绘制位置
    local gameName = {
    	text = title,
    	textX = cellSize * 12,
    	textY = cellSize * 6
    }
    
    -- 选项:开始和退出
    local options = {
    	{
    		text = "START",
    
    		textX = cellSize * 18,
    		textY = cellSize * 15 - 5,
    
    		border = {
    			cellSize*16, cellSize*14,
    			cellSize*24, cellSize*14,
    			cellSize*24, cellSize*17,
    			cellSize*16, cellSize*17,
    			cellSize*16, cellSize*14
    		}
    	},
    	{
    		text = "QUIT",
    
    		textX = cellSize * 19 - 10,
    		textY = cellSize * 19 - 5,
    
    		border = {
    			cellSize*16, cellSize*18,
    			cellSize*24, cellSize*18,
    			cellSize*24, cellSize*21,
    			cellSize*16, cellSize*21,
    			cellSize*16, cellSize*18
    		}
    	},
    
    	-- 一些其他属性
    	count = 2,
    	selected = 1
    }
    
    function love.load ()
    	-- 加载并播放背景音乐
    	sounds.showMenu:play ()
    
    	-- 设置米色和蓝色的透明程度为0,为了之后的动画效果
    	colors.beiga[4] = 0
    	colors.paleTurquoise[4] = 0
    end
    
    function love.draw ()
    	-- 灰色背景
    	love.graphics.setColor (colors.darkGray)
    	love.graphics.rectangle (
    		'fill',
    		0,
    		0,
    		width,
    		height
    	)
    
    	-- 白色边框
    	love.graphics.setColor (colors.white)
    	love.graphics.line (border)
    
    	-- 渐显效果
    	if colors.beiga[4] < 1 then
    		colors.beiga[4] = colors.beiga[4] + 0.01
    		colors.paleTurquoise[4] = colors.paleTurquoise[4] + 0.01
    	end
    
    	-- 设置字体,在指定位置画出米色标题
    	love.graphics.setFont (fonts.pixies100)
    	love.graphics.setColor (colors.beiga)
    	love.graphics.print (gameName.text, gameName.textX, gameName.textY)
    
    	-- 设置字体
    	love.graphics.setFont (fonts.pixies30)
    
    	-- 绘制所有选项
    	for i = 1, options.count do
    		if i == options.selected then
    			love.graphics.setColor (colors.paleTurquoise)
    		else
    			love.graphics.setColor (colors.beiga)
    		end
    
    		-- 绘制选项边框和字体
    		love.graphics.line (options[i].border)
    		love.graphics.print (options[i].text, options[i].textX, options[i].textY)
    	end
    end
    
    function love.keypressed (key)
    	-- 上下箭头选择选项,回车按键确认选项
    	if key == 'up' then
    		-- 关闭切换选项的声音并重新播放
    		if sounds.switchOption.isPlaying then
    			sounds.switchOption:stop ()
    		end
    		sounds.switchOption:play ()
    
    		-- 切换当前选项索引
    		options.selected = options.selected - 1
    		if options.selected <= 0 then
    			options.selected = options.count
    		end
    	elseif key == 'down' then
    		-- 同上
    		if sounds.switchOption.isPlaying then
    			sounds.switchOption:stop ()
    		end
    		sounds.switchOption:play ()
    
    		options.selected = options.selected + 1
    		if options.selected > options.count then
    			options.selected = 1
    		end
    	elseif key == 'return' then
    		-- 关闭显示界面声音
    		if sounds.showMenu.isPlaying then
    			sounds.showMenu:stop ()
    		end
    
    		-- 对应不同选项作出不同回应
    		if options.selected == 1 then
    			SwitchScence ('GameStart')
    		elseif options.selected == 2 then
    			love.event.quit ()
    		end
    	end
    end
    
    

    实现游戏主体

    游戏的实现方法,主要知道两个方面:

    • 蛇的移动方式:根据方向获取下一个头的位置,若没有吃到食物就将蛇尾删除,达到移动效果
    -- 下一个蛇头位置
    local nextX = snake.body[1].x
    local nextY = snake.body[1].y
    
    -- 当方向队列中的方向大于1时除去第一个方向(当前方向)
    if #directionQueue > 1 then
    	table.remove (directionQueue, 1)
    end
    
    -- 根据方向作出改动
    if directionQueue[1] == 'right' then
    	nextX = nextX + 1
    	if nextX > limit.x then
            nextX = 0
    	end
        elseif directionQueue[1] == 'left' then
            nextX = nextX - 1
            if nextX < 0 then
                nextX = limit.x
            end
        elseif directionQueue[1] == 'down' then
    	   nextY = nextY + 1
    	   if nextY > limit.y then
    		  nextY = 0
    	   end
        elseif directionQueue[1] == 'up' then
            nextY = nextY - 1
            if nextY < 0 then
                nextY = limit.y
            end
        end
    
        -- 蛇是否可以移动(没有与自身相撞)
        local canMove = true
        for index, pair in ipairs (snake.body) do
            if index ~= #snake.body
            and nextX == pair.x
            and nextY == pair.y then
                canMove = false
            end
        end
    
    	-- 当蛇可以移动时
    	if canMove then
            -- 将新位置加在蛇身的头,并检测是否吃到了食物
    		table.insert (snake.body, 1, { x = nextX, y = nextY })
    		if nextX == food.x and nextY == food.y then
                -- 播放吃到食物的音效(关闭之前的音效)
    			if sounds.eatFood.isPlaying then
    				sounds.eatFood:stop ()
    			end
    			sounds.eatFood:play ()
    
    			-- 分数加一,并生成新的食物位置
    			currentScore.score = currentScore.score + 1
    				CreateFood ()
    			else
    			-- 没有吃到食物则删去蛇身的尾部,达到移动的目的
    			table.remove (snake.body)
    		end
    	else
    	-- 蛇死亡,并播放相撞的音效
    		snake.alive = false
    		sounds.collided:play ()
    	end
    end
    
    
    • 方向队列的引入:主要是解决键位冲突的问题
    function love.keypressed (key)
    	-- 空格键暂停游戏
    	if key == 'space' then
    		paused = not paused
    	end
    
    	-- 没有暂停时
    	if not paused then
    		-- 记录方向键的按下顺序,同方向或相反方向的不记录
    		if key == 'right'
    		and directionQueue[#directionQueue] ~= 'right'
    		and directionQueue[#directionQueue] ~= 'left' then
    			table.insert (directionQueue, 'right')
    		elseif key == 'left'
    		and directionQueue[#directionQueue] ~= 'left'
    		and directionQueue[#directionQueue] ~= 'right' then
    			table.insert (directionQueue, 'left')
    		elseif key == 'down'
    		and directionQueue[#directionQueue] ~= 'down'
    		and directionQueue[#directionQueue] ~= 'up' then
    			table.insert (directionQueue, 'down')
    		elseif key == 'up'
    		and directionQueue[#directionQueue] ~= 'up'
    		and directionQueue[#directionQueue] ~= 'down' then
    			table.insert (directionQueue, 'up')
    		end
    	end
    end
    
    

    代码如下:

    -- 游戏窗口与记分窗口的分界线
    local boundary = {
    	cellSize*30, 0,
    	cellSize*30, height
    }
    
    -- 当前分数的信息
    local currentScore = {
    	text = 'SCORE',
    	score = 0,
    
    	-- 文字的绘图位置
    	textX = cellSize * 33,
    	textY = cellSize * 2,
    
    	-- 分数的绘图位置
    	scoreX = cellSize * 34,
    	scoreY = cellSize * 5
    }
    
    -- 最高分的信息
    local highScore = {
    	text = 'HIGH SCORE',
    	score = 0,
    
    	-- 同上
    	textX = cellSize * 31,
    	textY = cellSize * 12,
    
    	scoreX = cellSize * 34,
    	scoreY = cellSize * 15
    }
    
    -- 提示信息
    local notes = {
    	{
    		text = 'ARROW KEY TO MOVE',
    		textX = cellSize * 34,
    		textY = cellSize * 22
    	},
    	{
    		text = 'ENTER KEY TO PAUSE',
    		textX = cellSize * 34,
    		textY = cellSize * 23
    	}
    }
    
    -- 游戏窗口的限制
    local limit = { x = 29, y = 24 }
    
    -- 蛇的初始化信息
    local snake = {
    	-- 蛇身
    	body = {
    		{ x = 2, y = 0 },
    		{ x = 1, y = 0 },
    		{ x = 0, y = 0 }
    	},
    
    	-- 速度与状态
    	speed = 0.1,
    	alive = true,
    }
    
    -- 食物的位置
    local food = { x = nil, y = nil }
    
    -- 方向队列,用于记录键盘按下的顺序以免产生冲突
    local directionQueue = { 'right' }
    
    -- 计时器,暂停状态以及最高分文件
    local timer = 0
    local paused = false
    local file = nil
    
    -- 用于生成食物的可存在位置
    local function CreateFood ()
    	local foodPosition = {}
    
    	-- 遍历整个窗口,将可生成食物的位置记录在foodPosition表里
    	for i = 0, limit.x do
    		for j = 0, limit.y do
    			local possible = true
    
    			-- 是否与蛇身冲突
    			for index, pair in ipairs (snake.body) do
    				if i == pair.x and j == pair.y then
    					possible = false
    				end
    			end
    
    			if possible then
    				table.insert (foodPosition, { x = i, y = j })
    			end
    		end
    	end
    
    	-- 生成随机食物位置
    	local index = love.math.random (#foodPosition)
    	food.x, food.y = foodPosition[index].x, foodPosition[index].y
    end
    
    function love.load ()
    	file = love.filesystem.newFile ('HighScore.txt')
    	file:open ('r')
    	highScore.score = file:read ()
    	file:close ()
    
    	-- 没有透明度
    	colors.beiga[4] = 1
    	colors.paleTurquoise[4] = 1
    
    	CreateFood ()
    end
    
    function love.draw ()
    	-- 绘制背景
    	love.graphics.setColor (colors.darkGray)
    	love.graphics.rectangle (
    		'fill',
    		0,
    		0,
    		width,
    		height
    	)
    
    	-- 绘制白色边框和边界线
    	love.graphics.setColor (colors.white)
    	love.graphics.line (border)
    	love.graphics.line (boundary)
    
    	-- 设置字体和颜色,并在指定位置绘制当前分数信息和最高分信息
    	love.graphics.setFont (fonts.pixies30)
    	love.graphics.setColor (colors.beiga)
    	love.graphics.print (currentScore.text, currentScore.textX, currentScore.textY)
    	love.graphics.print (currentScore.score, currentScore.scoreX, currentScore.scoreY)
    	love.graphics.setColor (colors.paleTurquoise)
    	love.graphics.print (highScore.text, highScore.textX, highScore.textY)
    	love.graphics.print (highScore.score, highScore.scoreX, highScore.scoreY)
    
    	-- 蛇生存和死亡时使用不同的颜色绘制
    	if snake.alive then
    		love.graphics.setColor (colors.paleTurquoise)
    	else
    		love.graphics.setColor (colors.beiga)
    	end
    
    	-- 绘制蛇身,蛇头另绘
    	for index, pair in ipairs (snake.body) do
    		if index == 1 then
    			love.graphics.rectangle (
    				'fill',
    				cellSize*pair.x,
    				cellSize*pair.y,
    				cellSize,
    				cellSize
    			)
    		end
    		love.graphics.rectangle (
    			'fill',
    			cellSize*pair.x+1,
    			cellSize*pair.y+1,
    			cellSize-1*2,
    			cellSize-1*2
    		)
    	end
    
    	-- 绘制食物
    	love.graphics.setColor (colors.beiga)
    	love.graphics.rectangle (
    		'fill',
    		cellSize*food.x+1,
    		cellSize*food.y+1,
    		cellSize-1*2,
    		cellSize-1*2
    	)
    
    	-- 如果是暂停状态,则绘制暂停字样
    	if paused then
    		love.graphics.print ('PAUSED !', cellSize*12, cellSize*11)
    	end
    
    	-- 设置字体和颜色并绘制提示信息
    	love.graphics.setFont (fonts.pixies10)
    	love.graphics.setColor (colors.beiga)
    	for i = 1, #notes do
    		love.graphics.print (notes[i].text, notes[i].textX, notes[i].textY)
    	end
    end
    
    function love.update (dt)
    	-- 使用计时器
    	timer = timer + dt
    
    	-- 当蛇生存时
    	if snake.alive then
    		-- 根据蛇的速度更新游戏
    		if timer > snake.speed then
    			timer = timer - snake.speed
    
    			-- 没有暂停时
    			if not paused then
    				-- 下一个蛇头位置
    				local nextX = snake.body[1].x
    				local nextY = snake.body[1].y
    
    				-- 当方向队列中的方向大于1时除去第一个方向(当前方向)
    				if #directionQueue > 1 then
    					table.remove (directionQueue, 1)
    				end
    
    				-- 根据方向作出改动
    				if directionQueue[1] == 'right' then
    					nextX = nextX + 1
    					if nextX > limit.x then
    						nextX = 0
    					end
    				elseif directionQueue[1] == 'left' then
    					nextX = nextX - 1
    					if nextX < 0 then
    						nextX = limit.x
    					end
    				elseif directionQueue[1] == 'down' then
    					nextY = nextY + 1
    					if nextY > limit.y then
    						nextY = 0
    					end
    				elseif directionQueue[1] == 'up' then
    					nextY = nextY - 1
    					if nextY < 0 then
    						nextY = limit.y
    					end
    				end
    
    				-- 蛇是否可以移动(没有与自身相撞)
    				local canMove = true
    				for index, pair in ipairs (snake.body) do
    					if index ~= #snake.body
    					and nextX == pair.x
    					and nextY == pair.y then
    						canMove = false
    					end
    				end
    
    				-- 当蛇可以移动时
    				if canMove then
    					-- 将新位置加在蛇身的头,并检测是否吃到了食物
    					table.insert (snake.body, 1, { x = nextX, y = nextY })
    					if nextX == food.x and nextY == food.y then
    						-- 播放吃到食物的音效(关闭之前的音效)
    						if sounds.eatFood.isPlaying then
    							sounds.eatFood:stop ()
    						end
    						sounds.eatFood:play ()
    
    						-- 分数加一,并生成新的食物位置
    						currentScore.score = currentScore.score + 1
    						CreateFood ()
    					else
    						-- 没有吃到食物则删去蛇身的尾部,达到移动的目的
    						table.remove (snake.body)
    					end
    				else
    					-- 蛇死亡,并播放相撞的音效
    					snake.alive = false
    					sounds.collided:play ()
    				end
    			end
    		end
    	-- 等待一秒
    	elseif timer >= 1 then
    		-- 存储最高分
    		if currentScore.score > tonumber (highScore.score) then
    			file:open ('w')
    			file:write (tostring (currentScore.score))
    			file:close ()
    		end
    
    		-- 切换到游戏结束场景
    		SwitchScence ('GameOver')
    	end
    end
    
    function love.keypressed (key)
    	-- 回车键暂停游戏
    	if key == 'return' then
    		paused = not paused
    	end
    
    	-- 没有暂停时
    	if not paused then
    		-- 记录方向键的按下顺序,同方向或相反方向的不记录
    		if key == 'right'
    		and directionQueue[#directionQueue] ~= 'right'
    		and directionQueue[#directionQueue] ~= 'left' then
    			table.insert (directionQueue, 'right')
    		elseif key == 'left'
    		and directionQueue[#directionQueue] ~= 'left'
    		and directionQueue[#directionQueue] ~= 'right' then
    			table.insert (directionQueue, 'left')
    		elseif key == 'down'
    		and directionQueue[#directionQueue] ~= 'down'
    		and directionQueue[#directionQueue] ~= 'up' then
    			table.insert (directionQueue, 'down')
    		elseif key == 'up'
    		and directionQueue[#directionQueue] ~= 'up'
    		and directionQueue[#directionQueue] ~= 'down' then
    			table.insert (directionQueue, 'up')
    		end
    	end
    end
    
    

    实现最高分的保存与读取

    游戏存档目录:

    • Windows XP: C:Documents and SettingsuserApplication DataLOVE or %appdata%LOVE

    • Windows Vista and 7,8: C:UsersuserAppDataRoamingLOVE or %appdata%LOVE

    • Linux: $XDG_DATA_HOME/love/ or ~/.local/share/love/

    • Mac: /Users/user/Library/Application Support/LOVE/

    !写文件只能在存档目录

    最高分读取:

    file = love.filesystem.newFile ('HighScore.txt')
    file:open ('r')
    highScore.score = file:read ()
    file:close ()
    
    

    最高分保存:

    file:open ('w')
    file:write (tostring (currentScore.score))
    file:close ()
    
    

    绘制游戏结束界面

    游戏结束界面的绘制与开始界面大致相同,这里不再赘述

    代码如下:

    local gameOver = {
    	text = 'GAME OVER !',
    	textX = cellSize * 6,
    	textY = cellSize * 6
    }
    
    -- 选项:开始和退出
    local options = {
    	{
    		text = "BACK",
    
    		textX = cellSize * 13 - 15,
    		textY = cellSize * 17 - 5,
    
    		border = {
    			cellSize*10, cellSize*16,
    			cellSize*18, cellSize*16,
    			cellSize*18, cellSize*19,
    			cellSize*10, cellSize*19,
    			cellSize*10, cellSize*16
    		}
    	},
    	{
    		text = "RETRY",
    
    		textX = cellSize * 24,
    		textY = cellSize * 17 - 5,
    
    		border = {
    			cellSize*22, cellSize*16,
    			cellSize*30, cellSize*16,
    			cellSize*30, cellSize*19,
    			cellSize*22, cellSize*19,
    			cellSize*22, cellSize*16
    		}
    	},
    
    	-- 一些其他属性
    	count = 2,
    	selected = 1
    }
    
    function love.load ()
    	sounds.gameOver:play ()
    
    	-- 设置米色和蓝色的透明程度为0,为了之后的动画效果
    	colors.beiga[4] = 0
    	colors.paleTurquoise[4] = 0
    end
    
    function love.draw ()
    	-- 灰色背景
    	love.graphics.setColor (colors.darkGray)
    	love.graphics.rectangle (
    		'fill',
    		0,
    		0,
    		width,
    		height
    	)
    
    	-- 白色边框
    	love.graphics.setColor (colors.white)
    	love.graphics.line (border)
    
    	-- 渐显效果
    	if colors.beiga[4] < 1 then
    		colors.beiga[4] = colors.beiga[4] + 0.01
    		colors.paleTurquoise[4] = colors.paleTurquoise[4] + 0.01
    	end
    
    	-- 设置字体,在指定位置画出米色标题
    	love.graphics.setFont (fonts.pixies100)
    	love.graphics.setColor (colors.beiga)
    	love.graphics.print (gameOver.text, gameOver.textX, gameOver.textY)
    
    	-- 设置字体
    	love.graphics.setFont (fonts.pixies30)
    
    	for i = 1, options.count do
    		if i == options.selected then
    			love.graphics.setColor (colors.paleTurquoise)
    		else
    			love.graphics.setColor (colors.beiga)
    		end
    
    		love.graphics.line (options[i].border)
    		love.graphics.print (options[i].text, options[i].textX, options[i].textY)
    	end
    end
    
    function love.keypressed (key)
    	-- 上下箭头选择选项,回车按键确认选项
    	if key == 'left' then
    		if sounds.gameOver.isPlaying then
    			sounds.gameOver:stop ()
    		end
    
    		if sounds.switchOption.isPlaying then
    			sounds.switchOption:stop ()
    		end
    		sounds.switchOption:play ()
    
    		options.selected = options.selected - 1
    		if options.selected <= 0 then
    			options.selected = options.count
    		end
    	elseif key == 'right' then
    		if sounds.gameOver.isPlaying then
    			sounds.gameOver:stop ()
    		end
    
    		if sounds.switchOption.isPlaying then
    			sounds.switchOption:stop ()
    		end
    		sounds.switchOption:play ()
    
    		options.selected = options.selected + 1
    		if options.selected > options.count then
    			options.selected = 1
    		end
    	elseif key == 'return' then
    		if sounds.gameOver.isPlaying then
    			sounds.gameOver:stop ()
    		end
    
    		if options.selected == 1 then
    			SwitchScence ('Menu')
    		elseif options.selected == 2 then
    			SwitchScence ('GameStart')
    		end
    	end
    end
    

    项目结构

    项目结构图如下

    Love2D游戏引擎制作贪吃蛇游戏

    代码地址如下:
    http://www.demodashi.com/demo/15051.html

    注:本文著作权归作者,由demo大师代发,拒绝转载,转载需要作者授权

  • 相关阅读:
    CSS hack——不同浏览器的CSS应对法
    IE6对CSS支持Bug收集
    jQuery
    jQuery学习备忘
    MSSQLSERVER之发布-分发-订阅
    利用Resgen.exe 批量生成resources文件
    多语言处理
    c# winform 打包部署 自定义界面 或设置开机启动
    C#修改文件夹权限
    VS2008 Windows Form项目安装包生成详解
  • 原文地址:https://www.cnblogs.com/demodashi/p/10503475.html
Copyright © 2011-2022 走看看